Acessibilidade
Modo administração
Portal do Cidadão

Tudo da sua cidade, em um só lugar

Serviços, notícias, contas públicas e legislação do município reunidos em um portal claro e acessível. Busque ou navegue.

Mais acessados

Tudo em um só lugar

Central de Serviços

Todos os serviços e canais da Prefeitura, organizados por assunto — a um clique.

Comunicação oficial

Notícias e publicações

Notícias, leis, editais e avisos publicados pela Prefeitura.

Ver todas
Transparência

Encontre pelo assunto, não pela sigla

Tudo o que o município publica, organizado por área. Clique para abrir os atalhos.

Prestação de contas: relatórios bimestrais e balanços anuais.

Não achou? Peça a informação.

Todo cidadão tem direito de solicitar informações públicas. O pedido é gratuito e a Prefeitura responde no prazo legal.

Atendimento presencial (SIC)

Rua Marquês de Sapucaí, 317 – Centro
Segunda a sexta, 9h–12h e 13h–16h30
Tel.: (31) 3672-7672

Serviços ao cidadão

Resolva online

Os serviços mais procurados, ligados direto ao sistema certo.

"; w.document.open(); w.document.write(doc); w.document.close(); w.focus(); setTimeout(function(){ w.print(); }, 350); } function barras(arr){ const max = Math.max(1, ...arr.map(x => x.valor || 0)); return `
` + arr.map(x => { const pct = Math.max(2, Math.round((x.valor||0)/max*100)); return `
${esc(x.rotulo)}${brl(x.valor)} · ${x.quantidade}
`; }).join("") + `
`; } function montaChips(){ const box=$("da-chips"); if(!box) return; const presentes = [...CATS, OUTRAS].filter(c => situacoesPorCat[c.id] && situacoesPorCat[c.id].length); if(!presentes.length){ box.innerHTML=""; return; } box.innerHTML = `Situação:` + presentes.map(c => ``).join(""); box.querySelectorAll(".da-chip").forEach(ch => ch.addEventListener("click", () => { catAtiva = (catAtiva === ch.dataset.cat) ? "" : ch.dataset.cat; box.querySelectorAll(".da-chip").forEach(x => x.classList.toggle("ativo", x.dataset.cat === catAtiva)); execBusca(); })); } function preencheSelect(id, arr, rotulo){ const s=$(id); if(!s) return; const atual=s.value; s.innerHTML=``+(arr||[]).map(v=>``).join(""); s.value=atual; } // ---- acessibilidade do simulador (padrão GOV.UK) ---- function validar(){ const erros=[]; const v=parseValorBR($("da-valor").value); if(isNaN(v)||v<=0) erros.push({campo:"da-valor", msg:"Informe o valor original (maior que zero)."}); if(!$("da-venc").value) erros.push({campo:"da-venc", msg:"Informe a data de vencimento."}); if($("da-venc").value && $("da-calc").value && $("da-calc").value < $("da-venc").value) erros.push({campo:"da-calc", msg:"A data do cálculo não pode ser anterior ao vencimento."}); return erros; } function mostrarErros(erros){ const wrap=$("da-erro-sumario-wrap"); if(!wrap) return; wrap.innerHTML=``; const s=$("da-erro-sumario"); s.focus(); s.scrollIntoView({block:"center",behavior:"smooth"}); s.querySelectorAll("a[data-foco]").forEach(a=>a.addEventListener("click",ev=>{ ev.preventDefault(); const el=$(a.dataset.foco); if(el){ el.focus(); el.scrollIntoView({block:"center",behavior:"smooth"}); } })); } function limpaErros(){ const w=$("da-erro-sumario-wrap"); if(w) w.innerHTML=""; } // ---- consulta ---- const execBusca = async () => { const box=$("da-res"); const params=new URLSearchParams(); const q=$("da-q").value.trim(); if(q) params.set("q",q); const tipo=$("da-f-tipo").value; if(tipo) params.set("tipo",tipo); const ano=$("da-f-ano").value; if(ano) params.set("ano",ano); const ord=$("da-f-ord").value; if(ord && ord!=="recentes") params.set("ordenar",ord); if(catAtiva && situacoesPorCat[catAtiva] && situacoesPorCat[catAtiva].length) params.set("situacao", situacoesPorCat[catAtiva].join(",")); const vmin=parseValorBR($("da-vmin").value); if(!isNaN(vmin)) params.set("valor_min", vmin); const vmax=parseValorBR($("da-vmax").value); if(!isNaN(vmax)) params.set("valor_max", vmax); const temFiltro = q||tipo||ano||catAtiva||!isNaN(vmin)||!isNaN(vmax); if(!temFiltro){ box.innerHTML=jiVazio("Use os filtros, as categorias ou digite um termo para listar as inscrições."); return; } box.innerHTML=`

Carregando…

`; try{ const {resultados}=await apiPortal(`/api/divida-ativa/busca?${params.toString()}`); if(!resultados||!resultados.length){ box.innerHTML=jiVazio("Nenhuma inscrição encontrada."); return; } const cabeca=`

${resultados.length} resultado(s)${resultados.length>=200?" — mostrando os 200 primeiros":""}

`; box.innerHTML=cabeca+resultados.map(d=>{ const c=catDe(d.situacao); return `

CDA ${esc(d.numero_cda||"—")} · ${esc(d.tipo_tributo||"—")}

${esc(d.devedor_nome||"—")} · ${esc(d.devedor_documento||"—")}

${brl(d.valor_atualizado)} · ${esc(d.situacao||"—")} · inscrição ${d.ano||"—"}

`; }).join(""); }catch(e){ box.innerHTML=`
${svg(IC.info,18)}
Não foi possível carregar.Tente de novo em instantes.
`; } }; // ---- simulador ---- $("da-calcular").onclick = async () => { limpaErros(); const erros=validar(); if(erros.length){ $("da-sim-out").innerHTML=""; mostrarErros(erros); return; } const out=$("da-sim-out"); const payload={ valor_originario:$("da-valor").value, data_vencimento:$("da-venc").value, data_calculo:$("da-calc").value||hoje, correcao_percent:$("da-corr").value, multa_percent:$("da-multa").value, juros_mensal_percent:$("da-juros").value, honorarios_percent:$("da-hon").value }; out.innerHTML=`

Calculando…

`; try{ const r=await fetch(`${API_BASE_PORTAL}/api/divida-ativa/calcular`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload)}); const d=await r.json(); if(!r.ok){ out.innerHTML=""; mostrarErros([{campo:"da-valor", msg:d.erro||"Não foi possível calcular."}]); return; } const m=d.memoria; const meta=`${d.dias_atraso} dia(s) de atraso · ${d.meses_atraso} mês(es) · cálculo em ${new Date(d.parametros.data_calculo+"T00:00:00").toLocaleDateString("pt-BR")}`; const linhaTela=(rot,val,tot)=>`${rot}${brl(val)}`; const tabelaTela=` ${linhaTela("Valor original",m.principal)} ${linhaTela("(+) Atualização monetária",m.correcao)} ${linhaTela("(=) Valor atualizado",m.valor_corrigido)} ${linhaTela("(+) Multa",m.multa)} ${linhaTela("(+) Juros de mora",m.juros)} ${m.honorarios?linhaTela("(+) Honorários",m.honorarios):""} ${linhaTela("(=) Total estimado",m.total,true)}
`; out.innerHTML=`

Composição do débito

${esc(meta)}

${tabelaTela}

${esc(d.aviso)}

`; $("da-imprimir").onclick=()=>{ const linhaP=(rot,val,tot)=>""+rot+""+brl(val)+""; var tabelaP="" +linhaP("Valor original",m.principal) +linhaP("(+) Atualização monetária",m.correcao) +linhaP("(=) Valor atualizado",m.valor_corrigido) +linhaP("(+) Multa",m.multa) +linhaP("(+) Juros de mora",m.juros) +(m.honorarios?linhaP("(+) Honorários",m.honorarios):"") +linhaP("(=) Total estimado",m.total,true) +"
"; var corpo="

Composição do débito (simulação)

Dívida Ativa · "+meta+"

"+tabelaP+"
Atenção: "+d.aviso+"
"; imprimirDoc("Composição do débito — simulação", corpo); }; }catch(err){ out.innerHTML=""; mostrarErros([{campo:"da-valor", msg:"Não consegui concluir agora. Tente de novo em instantes."}]); } }; // wiring consulta $("da-b").onclick=execBusca; $("da-q").addEventListener("keydown",e=>{ if(e.key==="Enter") execBusca(); }); ["da-f-tipo","da-f-ano","da-f-ord"].forEach(id=>{ const s=$(id); if(s) s.addEventListener("change",execBusca); }); ["da-vmin","da-vmax"].forEach(id=>{ const el=$(id); if(el) el.addEventListener("keydown",e=>{ if(e.key==="Enter") execBusca(); }); }); // ações nos resultados (delegação) $("da-res").addEventListener("click", e=>{ const btn=e.target.closest("button[data-acao]"); if(!btn) return; if(btn.dataset.acao==="simular"){ $("da-valor").value=btn.dataset.valor||""; if(btn.dataset.venc) $("da-venc").value=btn.dataset.venc; limpaErros(); const bloco=document.querySelector(".da-bloco"); if(bloco) bloco.scrollIntoView({behavior:"smooth"}); $("da-valor").focus(); } else if(btn.dataset.acao==="imprimir"){ let d={}; try{ d=JSON.parse(btn.dataset.json); }catch(_){} var corpo="

Inscrição em Dívida Ativa

Documento informativo · não constitui CDA

" +"" +"" +"" +"" +"" +"" +"" +"" +"
Número da CDA"+(d.numero_cda||"—")+"
Tributo"+(d.tipo_tributo||"—")+"
Devedor"+(d.devedor_nome||"—")+" ("+(d.devedor_documento||"—")+")
Ano da inscrição"+(d.ano||"—")+"
Situação"+(d.situacao||"—")+"
Valor inscrito"+brl(d.valor_inscrito)+"
Valor atualizado (informado pelo oficial)"+brl(d.valor_atualizado)+"
" +"
Atenção: Documento informativo de transparência. Não constitui Certidão de Dívida Ativa nem valor oficial de cobrança. Para o valor de pagamento e a emissão de guia, use o sistema oficial.
"; imprimirDoc("Inscrição em Dívida Ativa — informativo", corpo); } }); // ---- painel (resumo) — carrega por último ---- (async () => { const box=$("da-painel"); try{ const r=await apiPortal("/api/divida-ativa/resumo"); const t=r.totais||{}; const cards=`

Inscrições

${(t.quantidade||0).toLocaleString("pt-BR")}

total de CDAs

Valor inscrito

${brl(t.valor_inscrito)}

soma original

Valor atualizado

${brl(t.valor_atualizado)}

informado pelo oficial

`; const agg={}; (r.por_situacao||[]).forEach(s=>{ const c=catDe(s.situacao); if(!agg[c.id]) agg[c.id]={rotulo:c.rotulo,cor:c.cor,valor:0,quantidade:0}; agg[c.id].valor+=s.valor||0; agg[c.id].quantidade+=s.quantidade||0; (situacoesPorCat[c.id]=situacoesPorCat[c.id]||[]).push(s.situacao); }); const ordemCat=[...CATS.map(c=>c.id),"outras"]; const arrSit=ordemCat.filter(id=>agg[id]).map(id=>agg[id]); const arrTrib=(r.por_tipo||[]).map(x=>({rotulo:x.tipo||"—",valor:x.valor,quantidade:x.quantidade,cor:"var(--navy,#163f6c)"})); const arrAno=(r.por_ano||[]).map(x=>({rotulo:String(x.ano||"—"),valor:x.valor,quantidade:x.quantidade,cor:"#b8860b"})); box.innerHTML=cards+`

Por situação

${arrSit.length?barras(arrSit):jiVazio("Sem dados.")}

Por tributo

${arrTrib.length?barras(arrTrib):jiVazio("Sem dados.")}

Por ano de inscrição

${arrAno.length?barras(arrAno):jiVazio("Sem dados.")}
`; montaChips(); }catch(e){ box.innerHTML=`
${svg(IC.info,18)}
Não foi possível carregar o panorama.Tente de novo em instantes.
`; } })(); // ---- opções dos dropdowns ---- (async () => { try{ const o=await apiPortal("/api/divida-ativa/opcoes"); preencheSelect("da-f-tipo",o.tributos,"Todos os tributos"); preencheSelect("da-f-ano",o.anos,"Todos os anos"); }catch(e){} })(); } }; const JI_GENERICAS = { "concursos": ["Servidores e Pessoal","Concursos e Processos Seletivos","Editais, inscrições, resultados e convocações de concursos públicos e processos seletivos da Prefeitura."], "secretarias": ["Institucional","Secretarias Municipais","Estrutura administrativa da Prefeitura: secretarias, áreas de atuação e formas de contato."], "competencias": ["Institucional","Competências dos Órgãos","Atribuições e competências legais das secretarias e órgãos da administração municipal."], "conselhos": ["Participação","Conselhos e Fundos Municipais","Conselhos municipais, fundos e instâncias de participação e controle social."], "pca": ["Licitações e Contratos","Plano de Contratações Anual (PCA)","Planejamento anual das contratações do município, conforme a Lei 14.133/2021."], "notas-oficiais": ["Comunicação oficial","Notas Oficiais","Comunicados e notas oficiais da Prefeitura de Sabará."], "habitacao": ["Serviços ao cidadão","Habitação","Programas habitacionais, cadastro e atendimento da política municipal de habitação."], "banco-empregos": ["Serviços ao cidadão","Banco de Empregos","Vagas e oportunidades de trabalho intermediadas pelo município."], "chamamento": ["Participação","Chamamento Público","Editais de chamamento público e credenciamento para entidades e sociedade civil."], "formularios-servidor": ["Servidores e Pessoal","Formulários do Servidor","Requerimentos e formulários para servidores municipais."], "cronograma-cestas": ["Servidores e Pessoal","Cronograma de Cestas","Cronograma de distribuição de cestas — Secretaria de Recursos Humanos."], "faq": ["Serviços ao cidadão","Perguntas Frequentes","Dúvidas comuns sobre os serviços públicos municipais e como resolvê-los."], "privacidade": ["Acesso à Informação","LGPD – Política de Privacidade","Como a Prefeitura de Sabará trata dados pessoais, conforme a Lei 13.709/2018 (LGPD)."] }; Object.keys(JI_GENERICAS).forEach(rota => { if(PAGINAS[rota] && !PAGINAS[rota].generica) return; // já existe página real const [eyebrow, titulo, intro] = JI_GENERICAS[rota]; PAGINAS[rota] = { eyebrow, titulo, intro, generica:true }; }); const JI_ALIAS = { "concursos":"concurso-publico", "notas-oficiais":"noticias", "t/leis":"decretos", "t/decretos":"decretos", "leis":"decretos" }; PAGINAS["lai"] = { eyebrow:"Acesso à Informação", titulo:"Lei de Acesso à Informação (LAI)", ref:false, intro:"A Lei nº 12.527/2011 garante a qualquer pessoa o direito de pedir e receber informações públicas.", corpo: `

Pela LAI, qualquer pessoa — sem precisar justificar — pode solicitar informações a órgãos públicos. O pedido é gratuito e a resposta tem prazo legal de 20 dias, prorrogável por mais 10.

Como pedir uma informação ao Município

  1. Acesse o e-SIC do Município pela plataforma federal Fala.BR;
  2. Identifique-se, descreva a informação desejada e envie;
  3. Guarde o número de protocolo para acompanhar a resposta.

Transparência ativa

Boa parte das informações já está publicada por iniciativa do próprio Município — consulte a área de Transparência, as Contas Públicas e a Remuneração de servidores.

Recursos

Se o pedido for negado ou respondido de forma incompleta, cabe recurso pela própria plataforma Fala.BR, com instâncias de revisão previstas na lei.

` }; /* ===================== ACESSIBILIDADE (e-MAG / Decreto 5.296/2004) ======= */ /* ============ OUVIDORIA — registro, acompanhamento e avaliação ============ */ const OUV_TIPOS = [ ["denuncia","Denúncia","ti-alert-triangle","Irregularidade ou ato ilícito contra a administração pública."], ["reclamacao","Reclamação","ti-mood-sad","Insatisfação com um serviço público ou com o atendimento."], ["solicitacao","Solicitação","ti-clipboard-text","Pedido de um serviço ou providência da Prefeitura."], ["sugestao","Sugestão","ti-bulb","Ideia para melhorar serviços e políticas públicas."], ["elogio","Elogio","ti-thumb-up","Reconhecimento de um bom atendimento ou serviço."], ["simplifique","Simplifique","ti-wand","Proposta para desburocratizar um serviço público."], ]; function ouvFormHTML(){ return `
${OUV_TIPOS.map((t,i)=>``).join("")}

Seus dados são usados apenas para tratar esta manifestação, conforme a LGPD (Lei nº 13.709/2018). Em denúncias, a identidade do manifestante é preservada desde o registro (art. 10, §7º, da Lei nº 13.460/2017).

`; } function ouvLigar(){ const $$ = id => document.getElementById(id); const sec = $$("ouv-sec"); if(sec) fetch("/api/portal/transparencia/tipos").then(()=>{}).catch(()=>{}); ["Governo","Administração","Planejamento","Fazenda","Procuradoria","Recursos Humanos","Educação", "Saúde","Desenvolvimento Social","Obras","Meio Ambiente","Cultura","Turismo","Esporte", "Defesa Social","Defesa Civil"].forEach(s => { if(sec){ const o = document.createElement("option"); o.value = o.textContent = s; sec.appendChild(o); } }); let tipo = "denuncia"; document.querySelectorAll("#ouv-tipos .ouv-tipo").forEach(b => b.onclick = () => { document.querySelectorAll("#ouv-tipos .ouv-tipo").forEach(x => x.classList.remove("ativa")); b.classList.add("ativa"); tipo = b.dataset.tipo; }); document.querySelectorAll("#ouv-abas .ouv-aba").forEach(b => b.onclick = () => { document.querySelectorAll("#ouv-abas .ouv-aba").forEach(x => x.classList.remove("ativa")); b.classList.add("ativa"); $$("ouv-p-registrar").hidden = b.dataset.ouv !== "registrar"; $$("ouv-p-acompanhar").hidden = b.dataset.ouv !== "acompanhar"; }); const teor = $$("ouv-teor"), conta = $$("ouv-conta"); if(teor) teor.addEventListener("input", () => { const n = teor.value.trim().length; conta.textContent = `${n} caracteres` + (n < 20 ? " — mínimo de 20" : ""); conta.classList.toggle("ok", n >= 20); }); const anon = $$("ouv-anon"); if(anon) anon.addEventListener("change", () => { $$("ouv-ident").style.display = anon.checked ? "none" : ""; }); const btn = $$("ouv-enviar"); if(btn) btn.onclick = async () => { const saida = $$("ouv-saida"); const corpo = { tipo, assunto: $$("ouv-assunto").value, teor: $$("ouv-teor").value, local_fato: $$("ouv-local").value, secretaria: $$("ouv-sec").value, anonimo: anon.checked, nome: $$("ouv-nome").value, email: $$("ouv-email").value, telefone: $$("ouv-tel").value }; btn.disabled = true; btn.innerHTML = ` Enviando…`; try{ const r = await fetch("/api/portal/ouvidoria/manifestacao", { method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(corpo)}); const js = await r.json(); if(!r.ok) throw new Error(js.erro || "Não foi possível registrar."); saida.innerHTML = `

Manifestação registrada

Anote estes dados — é com eles que você acompanha a resposta:

Protocolo${esc(js.protocolo)}
Chave${esc(js.chave)}

Prazo de resposta: até ${js.prazo_fim.split("-").reverse().join("/")}.

`; const cp = $$("ouv-copiar"); if(cp) cp.onclick = () => { const txt = `Protocolo: ${js.protocolo} — Chave: ${js.chave}`; (navigator.clipboard ? navigator.clipboard.writeText(txt) : Promise.reject()) .then(() => { cp.innerHTML = ` Copiado`; }) .catch(() => { cp.textContent = txt; }); }; ["ouv-assunto","ouv-teor","ouv-local","ouv-nome","ouv-email","ouv-tel"].forEach(i => { if($$(i)) $$(i).value = ""; }); saida.scrollIntoView({behavior:"smooth", block:"center"}); }catch(e){ saida.innerHTML = `
${esc(e.message)}
`; }finally{ btn.disabled = false; btn.innerHTML = ` Enviar manifestação`; } }; const bb = $$("ouv-buscar"); if(bb) bb.onclick = async () => { const alvo = $$("ouv-resultado"); const p = ($$("ouv-cp").value || "").trim(), k = ($$("ouv-ck").value || "").trim(); alvo.innerHTML = `

Consultando…

`; try{ const r = await fetch(`/api/portal/ouvidoria/consulta?protocolo=${encodeURIComponent(p)}&chave=${encodeURIComponent(k)}`); const js = await r.json(); if(!r.ok) throw new Error(js.erro || "Não encontramos essa manifestação."); const m = js.manifestacao; const dt = s => s ? s.slice(0,10).split("-").reverse().join("/") : "—"; alvo.innerHTML = `
${esc(m.status_rotulo)} ${esc(m.protocolo)}${esc(m.tipo_rotulo)} · registrada em ${dt(m.criado_em)}
${m.assunto ? `

${esc(m.assunto)}

` : ""}

${esc(m.teor)}

${m.resposta ? `
Resposta da Ouvidoria

${esc(m.resposta)}

Respondida em ${dt(m.respondido_em)}
` : `

Ainda sem resposta. Prazo até ${dt(m.prazo_fim)}.

`}
${m.pode_avaliar ? `

Como você avalia este atendimento?

${[1,2,3,4,5].map(n=>``).join("")}
` : ""}`; if(m.pode_avaliar){ let nota = 0; const estrelas = document.querySelectorAll("#ouv-estrelas button"); estrelas.forEach(b => b.onclick = () => { nota = +b.dataset.n; estrelas.forEach(x => x.classList.toggle("on", +x.dataset.n <= nota)); }); $$("ouv-avaliar").onclick = async () => { if(!nota) return alert("Escolha de 1 a 5 estrelas."); const r2 = await fetch("/api/portal/satisfacao", {method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify({protocolo:p, chave:k, nota, resolvido: $$("ouv-resolvido").value, comentario: $$("ouv-coment").value})}); const j2 = await r2.json(); $$("ouv-aval").innerHTML = `

${esc(j2.mensagem || j2.erro || "Obrigado!")}

`; }; } }catch(e){ alvo.innerHTML = `
${esc(e.message)}
`; } }; } /* ================= CASA PARA TODOS — cadastro habitacional ================= */ const HAB_MORADIA_OPC = [["aluguel","Aluguel"],["cedida","Cedida/emprestada"], ["financiada","Financiada"],["propria_irregular","Própria em área irregular"], ["area_risco","Área de risco"],["coabitacao","Coabitação (mora com outra família)"], ["sem_teto","Sem moradia"],["outro","Outra situação"]]; function habFormCampos(v){ v = v || {}; const opc = (lista, atual) => lista.map(([k,r]) => ``).join(""); return `
`; } function habLerCampos(){ const g = id => (document.getElementById(id)||{}).value || ""; const ck = id => !!(document.getElementById(id)||{}).checked; return { nome:g("hb-nome"), cpf:g("hb-cpf"), nascimento:g("hb-nasc"), telefone:g("hb-tel"), email:g("hb-email"), nis:g("hb-nis"), endereco:g("hb-end"), bairro:g("hb-bairro"), tempo_municipio:g("hb-tempo"), pessoas:g("hb-pessoas"), renda_familiar:g("hb-renda"), situacao_moradia:g("hb-moradia"), observacoes:g("hb-obs"), mulher_chefe:ck("hb-mulher"), tem_idoso:ck("hb-idoso"), tem_pcd:ck("hb-pcd"), tem_crianca:ck("hb-crianca") }; } PAGINAS["habitacao"] = { eyebrow:"Habitação", titulo:"Casa Para Todos", ref:false, intro:"Cadastro habitacional de Sabará — para levantar a demanda por moradia e habilitar as famílias aos programas habitacionais do Município. O cadastro é on-line, permanente e pode ser atualizado a qualquer tempo.", aoMontar: habLigar, corpo: () => `
Famílias cadastradas
Mulher chefe de família
Com pessoa idosa
Com pessoa com deficiência

Objetivo

Abertura de cadastro habitacional com o intuito de fazer levantamento da demanda por moradia no município. Propor políticas públicas que atendam a necessidade da população de Sabará e garantam a função social da propriedade, melhorando a qualidade de vida e a dignidade dos munícipes.

Justificativa

O acesso à moradia e o enfrentamento das questões urbanas são prioridades de governo. A inexistência de iniciativas voltadas para a habitação de interesse social acarretou aumento da demanda para o setor. Atuar nessa frente é um grande desafio assumido pela atual gestão.

Atendimento

Para agendamento presencial é necessário entrar em contato previamente.

Contato

Tel./WhatsApp: +55 (31) 9765-2131
habitacaosocial@sabara.mg.gov.br

Local

Largo do Marquês
Rua Marquês de Sapucaí, 317 – Centro
Seg. a sex., 8h às 12h e 13h às 17h

Iniciativas do programa

Elegibilidade das famílias conforme os critérios da Portaria MCID nº 738/2024.

${[["Conselho Gestor","Nomeação e posse do Conselho Gestor Municipal de Habitação de Interesse Social","ti-users-group"], ["Fundo Municipal","Regularização do Fundo Municipal de Habitação de Interesse Social","ti-building-bank"], ["Plano Municipal","Plano Municipal de Habitação de Interesse Social","ti-map-2"], ["Cadastro habitacional","Levantamento permanente da demanda por moradia","ti-clipboard-list"], ["Regularização fundiária","Titulação e segurança jurídica da posse","ti-file-certificate"], ["Minha Casa Minha Vida","Adesão aos empreendimentos do programa federal","ti-home-2"], ["Trabalho social","Plano de Trabalho Social com as famílias do MCMV (pré, durante e pós-morar)","ti-heart-handshake"], ["Reurb","Regularização Fundiária Urbana","ti-map-pin-check"], ["Aluguel social","Apoio emergencial à moradia","ti-key"]].map(([t,d,i]) => `
${esc(t)}${esc(d)}
`).join("")}

Participe do cadastramento habitacional

Preencha os dados do responsável familiar. O cadastro é gratuito e não garante, por si só, a entrega de moradia — ele habilita a família a ser considerada nos programas conforme os critérios legais.

${habFormCampos()}

Seus dados são tratados apenas para a política habitacional do Município, conforme a LGPD (Lei nº 13.709/2018). A lista pública divulga somente nome e situação — nunca CPF, endereço ou renda.

Documentos para a inscrição

Apresentar os documentos originais de todos os membros da família no atendimento presencial:

  • Documento de identidade e CPF de todos os membros
  • Certidão de nascimento ou casamento
  • Comprovante de residência atualizado
  • Comprovante de renda de todos que trabalham
  • Comprovante do NIS/CadÚnico, se houver
  • Laudo médico, no caso de pessoa com deficiência
` }; function habLigar(){ const $$ = id => document.getElementById(id); fetch("/api/portal/habitacao/indicadores").then(r=>r.json()).then(d => { const cx = $$("hab-nums"); if(!cx) return; const vals = [d.total, d.mulher_chefe, d.com_idosos, d.pcd]; cx.querySelectorAll(".hab-num b").forEach((b,i) => b.textContent = (vals[i]||0).toLocaleString("pt-BR")); }).catch(()=>{}); document.querySelectorAll("#hab-abas .ouv-aba").forEach(b => b.onclick = () => { document.querySelectorAll("#hab-abas .ouv-aba").forEach(x => x.classList.remove("ativa")); b.classList.add("ativa"); $$("hab-p-novo").hidden = b.dataset.hab !== "novo"; $$("hab-p-atualizar").hidden = b.dataset.hab !== "atualizar"; }); const bt = $$("hb-enviar"); if(bt) bt.onclick = async () => { const saida = $$("hb-saida"); bt.disabled = true; bt.innerHTML = ` Enviando…`; try{ const r = await fetch("/api/portal/habitacao/cadastro", {method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(habLerCampos())}); const js = await r.json(); if(!r.ok) throw new Error(js.erro || "Não foi possível cadastrar."); saida.innerHTML = `

Cadastro realizado

${esc(js.mensagem||"")}

Protocolo${esc(js.protocolo)}
Chave${esc(js.chave)}
`; saida.scrollIntoView({behavior:"smooth", block:"center"}); fetch("/api/portal/habitacao/indicadores").then(r=>r.json()).then(d=>{ const vals=[d.total,d.mulher_chefe,d.com_idosos,d.pcd]; document.querySelectorAll("#hab-nums .hab-num b").forEach((b,i)=>b.textContent=(vals[i]||0).toLocaleString("pt-BR")); }).catch(()=>{}); }catch(e){ saida.innerHTML = `
${esc(e.message)}
`; }finally{ bt.disabled=false; bt.innerHTML = ` Enviar cadastro`; } }; const bb = $$("hb-buscar"); if(bb) bb.onclick = async () => { const alvo = $$("hb-resultado"); const p = ($$("hb-cp").value||"").trim(), k = ($$("hb-ck").value||"").trim(); alvo.innerHTML = `

Consultando…

`; try{ const r = await fetch(`/api/portal/habitacao/consulta?protocolo=${encodeURIComponent(p)}&chave=${encodeURIComponent(k)}`); const js = await r.json(); if(!r.ok) throw new Error(js.erro || "Não encontramos esse cadastro."); const c = js.cadastro; alvo.innerHTML = `
${esc(c.status_rotulo)}${esc(c.protocolo)} ${esc(c.nome)}
${c.parecer ? `
Parecer da Habitação

${esc(c.parecer)}

` : ""}

Atualizar meus dados

${habFormCampos(c)}
`; const nome = $$("hb-nome"), cpf = $$("hb-cpf"); if(nome){ nome.readOnly = true; nome.style.opacity=".7"; } if(cpf){ cpf.readOnly = true; cpf.style.opacity=".7"; } $$("hb-salvar").onclick = async () => { const corpo = Object.assign(habLerCampos(), {protocolo:p, chave:k}); const r2 = await fetch("/api/portal/habitacao/cadastro", {method:"PUT", headers:{"Content-Type":"application/json"}, body: JSON.stringify(corpo)}); const j2 = await r2.json(); $$("hb-saida2").innerHTML = r2.ok ? `

${esc(j2.mensagem)}

` : `
${esc(j2.erro||"Erro")}
`; }; }catch(e){ alvo.innerHTML = `
${esc(e.message)}
`; } }; } /* ================= CADASTRO DE FORNECEDOR (CRC municipal) ================= */ PAGINAS["cadastro-fornecedor"] = { eyebrow:"Empresas e Fornecedores", titulo:"Cadastre sua Empresa", ref:false, intro:"Cadastro de fornecedores do Município de Sabará. O cadastro reúne os dados e documentos da empresa para participação em licitações e contratações, conforme a Lei nº 14.133/2021.", aoMontar: fornLigar, corpo: () => `

Após o envio, a Prefeitura confere a documentação e emite o Certificado de Registro Cadastral (CRC). A habilitação em cada licitação segue as regras do respectivo edital.

Documentos exigidos

Habilitação jurídica

  • Ato constitutivo, estatuto ou contrato social
  • Documento do representante legal
  • Certificado do MEI, quando for o caso

Regularidade fiscal

  • CND federal, estadual e municipal
  • FGTS (CRF)
  • Certidão trabalhista (CNDT)

Qualificação técnica e econômica

  • Atestados de capacidade técnica
  • Balanço patrimonial, quando exigido
  • Certidão negativa de falência

Os documentos são apresentados no atendimento do setor de Compras ou anexados quando solicitados pela Prefeitura após o envio deste cadastro.

` }; function fornLigar(){ const $$ = id => document.getElementById(id); document.querySelectorAll("#forn-abas .ouv-aba").forEach(b => b.onclick = () => { document.querySelectorAll("#forn-abas .ouv-aba").forEach(x => x.classList.remove("ativa")); b.classList.add("ativa"); $$("forn-p-novo").hidden = b.dataset.forn !== "novo"; $$("forn-p-consulta").hidden = b.dataset.forn !== "consulta"; }); const bt = $$("fn-enviar"); if(bt) bt.onclick = async () => { const g = id => ($$(id)||{}).value || ""; bt.disabled = true; bt.innerHTML = ` Enviando…`; try{ const r = await fetch("/api/portal/fornecedor", {method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify({ razao_social:g("fn-razao"), cnpj:g("fn-cnpj"), fantasia:g("fn-fantasia"), porte:g("fn-porte"), inscricao_estadual:g("fn-ie"), inscricao_municipal:g("fn-im"), ramo:g("fn-ramo"), cnae:g("fn-cnae"), endereco:g("fn-end"), cep:g("fn-cep"), municipio:g("fn-mun"), uf:g("fn-uf"), telefone:g("fn-tel"), email:g("fn-email"), representante:g("fn-rep"), representante_cpf:g("fn-repcpf")})}); const js = await r.json(); if(!r.ok) throw new Error(js.erro || "Não foi possível cadastrar."); $$("fn-saida").innerHTML = `

Cadastro enviado

${esc(js.mensagem||"")}

Protocolo${esc(js.protocolo)}
Chave${esc(js.chave)}
`; $$("fn-saida").scrollIntoView({behavior:"smooth", block:"center"}); }catch(e){ $$("fn-saida").innerHTML = `
${esc(e.message)}
`; }finally{ bt.disabled=false; bt.innerHTML=` Enviar cadastro`; } }; const bb = $$("fn-buscar"); if(bb) bb.onclick = async () => { const p = ($$("fn-cp").value||"").trim(), k = ($$("fn-ck").value||"").trim(); const alvo = $$("fn-resultado"); try{ const r = await fetch(`/api/portal/fornecedor/consulta?protocolo=${encodeURIComponent(p)}&chave=${encodeURIComponent(k)}`); const js = await r.json(); if(!r.ok) throw new Error(js.erro||"Não encontrado."); const f = js.fornecedor; const dt = s => s ? s.slice(0,10).split("-").reverse().join("/") : "—"; alvo.innerHTML = `
${esc(f.status_rotulo)} ${esc(f.protocolo)}${esc(f.razao_social)} · ${esc(f.cnpj)}
${f.validade ? `

Cadastro válido até ${dt(f.validade)}.

` : ""} ${f.parecer ? `
Parecer

${esc(f.parecer)}

` : ""}
`; }catch(e){ alvo.innerHTML = `
${esc(e.message)}
`; } }; } /* ══════════════════════════════════════════════════════════════════════ AVISO DE PRIVACIDADE E CANAL DO TITULAR — LGPD O conteúdo vem da API, que o monta a partir do registro de tratamentos (lgpd_registro.py). Assim, o que a lei manda informar e o que o sistema realmente faz não podem divergir: é a mesma fonte. ══════════════════════════════════════════════════════════════════════ */ PAGINAS["privacidade"] = { eyebrow:"Proteção de dados", titulo:"Privacidade e proteção de dados", ref:false, intro:"Como o Município trata os seus dados pessoais, com que finalidade, "+ "por quanto tempo e como você exerce os seus direitos.", corpo: `

Carregando…

` }; async function jiPrivacidade(){ const alvo = document.getElementById("lgpd-corpo"); if(!alvo) return; let j; try{ j = await (await fetch("/api/portal/privacidade")).json(); } catch(e){ alvo.innerHTML = "

Não foi possível carregar agora.

"; return; } const enc = j.encarregado || {}; const blocoEnc = enc.indicado ? `

Encarregado pelo tratamento de dados pessoais

Conforme o art. 41 da LGPD, esta é a pessoa indicada para receber as suas reclamações e prestar esclarecimentos.

${esc(enc.nome)}${enc.cargo?` — ${esc(enc.cargo)}`:""}
${enc.email?`E-mail: ${esc(enc.email)}
`:""} ${enc.telefone?`Telefone: ${esc(enc.telefone)}
`:""} ${enc.ato_nomeacao?`Ato de nomeação: ${esc(enc.ato_nomeacao)}`:""}

` : `

Encarregado ainda não indicado

O art. 41 da LGPD exige que o controlador indique um Encarregado e divulgue o contato. Enquanto isso não ocorre, use os canais da Ouvidoria.

`; const cards = (j.tratamentos||[]).map(t=>`
${esc(t.nome)} ${t.sensivel?'dado sensível':""} ${t.criancas?'dados de criança':""}

Para que serve: ${esc(t.finalidade)}

Dados tratados: ${(t.dados||[]).map(esc).join(", ")}

${t.observacao_dados?`

${esc(t.observacao_dados)}

`:""}

Base legal: ${(t.bases_legais||[]).map(esc).join("; ")}

${t.previsao_legal?`

Previsão legal: ${esc(t.previsao_legal)}

`:""}

Por quanto tempo guardamos: ${esc(t.guarda_texto||"")}

Com quem compartilhamos: ${esc(t.compartilhamento||"—")}

${t.nota_melhor_interesse?`

Melhor interesse da criança (art. 14): ${esc(t.nota_melhor_interesse)}

`:""}
`).join(""); const direitos = (j.direitos||[]).map(d=> ``).join(""); alvo.innerHTML = `

O ${esc((j.controlador||{}).nome||"Município")} é o controlador dos dados pessoais tratados neste portal, nos termos da Lei nº 13.709/2018 (LGPD). Esta página cumpre o dever de informar previsto no art. 9º e no art. 23, I da Lei.

${blocoEnc}

O que fazemos com dados pessoais

Cada item abaixo é uma finalidade diferente. Clique para ver quais dados são usados, com que fundamento legal e por quanto tempo.

${cards} ${j.tem_dados_de_criancas?`

Dados de crianças e adolescentes

O tratamento se dá no melhor interesse da criança (art. 14 da LGPD), com fundamento nas hipóteses do art. 7º, conforme o Enunciado CD/ANPD nº 1, de 24/05/2023. Os tipos de dados coletados, a forma de uso e o caminho para exercer direitos estão nesta página, como exige o art. 14, § 2º.

`:""}

Seus direitos

O art. 18 da LGPD garante os direitos abaixo. O pedido é gratuito (art. 18, § 5º) e será respondido em até ${j.prazo_resposta_dias||15} dias.

Fazer um pedido

Não peça nem envie cópia de documento por aqui. Precisamos apenas do suficiente para não entregar seus dados a outra pessoa.

Acompanhar um pedido

Se não ficar satisfeito com a resposta, você pode peticionar à Autoridade Nacional de Proteção de Dados (ANPD), nos termos do art. 18, § 1º da LGPD.

Atualizado em ${esc(j.atualizado_em||"")}.

`; document.getElementById("lg-enviar").onclick = async () => { const res = document.getElementById("lg-result"); const corpo = { tipo: document.getElementById("lg-tipo").value, nome: document.getElementById("lg-nome").value, email: document.getElementById("lg-email").value, telefone: document.getElementById("lg-tel").value, identificacao: document.getElementById("lg-ident").value, descricao: document.getElementById("lg-desc").value}; res.innerHTML = "

Enviando…

"; try{ const r = await fetch("/api/portal/titular/pedido", {method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(corpo)}); const d = await r.json(); if(!r.ok){ res.innerHTML = `

${esc(d.erro||"Não foi possível enviar.")}

`; return; } res.innerHTML = `

Pedido registrado. Anote — a chave aparece só agora:

Protocolo: ${esc(d.protocolo)}
Chave: ${esc(d.chave)}

Resposta até ${esc(d.prazo_fim)}.

`; }catch(e){ res.innerHTML = `

Falha de conexão.

`; } }; document.getElementById("lg-consultar").onclick = async () => { const res = document.getElementById("lg-consulta-res"); const pr = document.getElementById("lg-cprot").value.trim(); const ck = document.getElementById("lg-cchave").value.trim(); res.innerHTML = "

Consultando…

"; try{ const r = await fetch(`/api/portal/titular/consulta?protocolo=${encodeURIComponent(pr)}&chave=${encodeURIComponent(ck)}`); const d = await r.json(); if(!r.ok){ res.innerHTML = `

${esc(d.erro||"Não encontrado.")}

`; return; } const p = d.pedido||{}; res.innerHTML = `

${esc(p.tipo_rotulo||"")} — ${esc(p.artigo||"")}

Situação: ${esc(p.status||"")} · Prazo: ${esc(p.prazo_fim||"—")}

${p.resposta?`

Resposta:
${esc(p.resposta)}

`:"

Ainda sem resposta.

"}
`; }catch(e){ res.innerHTML = `

Falha de conexão.

`; } }; } /* Recadastramento de sepulturas — substitui o sistema antigo, que saía do portal e vivia fora do ar. */ PAGINAS["sepulturas"] = { eyebrow:"Cemitério Municipal", titulo:"Recadastramento de sepulturas", ref:false, intro:"Atualize os dados do responsável pela sepultura ou jazigo e envie "+ "os comprovantes. Serve para identificar quem responde por cada "+ "espaço e regularizar a documentação da perpetuidade.", corpo:`

Carregando…

` }; async function jiSepulturas(){ const alvo = document.getElementById("cem-corpo"); if(!alvo) return; let cfg; try{ cfg = await (await fetch("/api/portal/sepulturas/config")).json(); } catch(e){ alvo.innerHTML="

Não foi possível carregar agora.

"; return; } alvo.innerHTML = `

Antes de começar

Tenha em mãos: título ou guia de concessão da perpetuidade, documento de identidade e comprovante de residência do titular e do segundo representante, e a certidão de óbito de ao menos um dos sepultados.

Importante: a pessoa indicada como titular passa a responder pela perpetuidade, inclusive pelas taxas correspondentes.

1. Onde fica a sepultura

2. Titular da perpetuidade

3. Segundo representante

Exigido no recadastramento. É quem a Prefeitura procura se não localizar o titular.

4. Quem está sepultado

5. Observações

Já enviei — quero acompanhar ou anexar documento

`; // linhas de sepultados const box = document.getElementById("cm-sepultados"); function linha(){ const d = document.createElement("div"); d.className = "lgpd-2col"; d.style.marginBottom = "8px"; d.innerHTML = `
`; d.querySelector("button").onclick = () => d.remove(); box.appendChild(d); } linha(); document.getElementById("cm-add").onclick = linha; const v = id => (document.getElementById(id)||{}).value || ""; document.getElementById("cm-enviar").onclick = async () => { const res = document.getElementById("cm-result"); const sepultados = [...box.querySelectorAll(".lgpd-2col")].map(l=>({ nome: (l.querySelector(".cm-sep-nome")||{}).value||"", obito:(l.querySelector(".cm-sep-obito")||{}).value||""})).filter(x=>x.nome.trim()); const corpo = { cemiterio:v("cm-cem"), tipo:v("cm-tipo"), quadra:v("cm-quadra"), numero:v("cm-numero"), complemento:v("cm-compl"), titulo_concessao:v("cm-titulo"), titular_nome:v("cm-tnome"), titular_cpf:v("cm-tcpf"), titular_rg:v("cm-trg"), titular_telefone:v("cm-ttel"), titular_email:v("cm-tmail"), titular_endereco:v("cm-tend"), titular_falecido:(document.getElementById("cm-tfalecido")||{}).checked, segundo_nome:v("cm-snome"), segundo_cpf:v("cm-scpf"), segundo_telefone:v("cm-stel"), segundo_parentesco:v("cm-spar"), sepultados, observacoes:v("cm-obs"), declara_responsabilidade:(document.getElementById("cm-declara")||{}).checked}; res.innerHTML = "

Enviando…

"; try{ const r = await fetch("/api/portal/sepulturas", {method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify(corpo)}); const d = await r.json(); if(!r.ok){ res.innerHTML = `

${esc(d.erro||"Não foi possível enviar.")}

`; return; } res.innerHTML = `

Recadastramento recebido. Anote — a chave aparece só agora:

Protocolo: ${esc(d.protocolo)}
Chave: ${esc(d.chave)}

Use os dois abaixo, em "Já enviei", para anexar os comprovantes.

`; document.getElementById("cm-cprot").value = d.protocolo; document.getElementById("cm-cchave").value = d.chave; }catch(e){ res.innerHTML = `

Falha de conexão.

`; } }; document.getElementById("cm-consultar").onclick = async () => { const res = document.getElementById("cm-consulta-res"); const pr = v("cm-cprot").trim(), ck = v("cm-cchave").trim(); res.innerHTML = "

Consultando…

"; try{ const r = await fetch(`/api/portal/sepulturas/consulta?protocolo=${encodeURIComponent(pr)}&chave=${encodeURIComponent(ck)}`); const d = await r.json(); if(!r.ok){ res.innerHTML = `

${esc(d.erro||"Não encontrado.")}

`; return; } const c = d.cadastro||{}; res.innerHTML = `

${esc(c.tipo||"")} ${esc(c.quadra?("quadra "+c.quadra+", "):"")}nº ${esc(c.numero||"")} — ${esc(c.cemiterio||"")}

Situação: ${esc(c.status_rotulo||c.status||"")}

${c.parecer?`

Parecer: ${esc(c.parecer)}

`:""}

Documentos enviados: ${(c.documentos||[]).length ? (c.documentos||[]).map(x=>esc(x.nome)).join(", ") : "nenhum ainda"}

${(c.faltam||[]).length?`

Ainda faltam:
${ (c.faltam||[]).map(f=>"• "+esc(f.rotulo)).join("
")}

`: "

Toda a documentação básica foi enviada.

"}
`; document.getElementById("cm-denviar").onclick = async () => { const dres = document.getElementById("cm-dres"); const f = (document.getElementById("cm-darq")||{}).files||[]; if(!f.length){ dres.innerHTML = '

Escolha o arquivo.

'; return; } const fd = new FormData(); fd.append("chave", ck); fd.append("tipo", v("cm-dtipo")); fd.append("arquivo", f[0]); dres.innerHTML = "

Enviando…

"; try{ const rr = await fetch(`/api/portal/sepulturas/${encodeURIComponent(pr)}/documentos`, {method:"POST", body:fd}); const dd = await rr.json(); dres.innerHTML = rr.ok ? '

Documento enviado.

' : `

${esc(dd.erro||"Falha ao enviar.")}

`; if(rr.ok) document.getElementById("cm-consultar").click(); }catch(e){ dres.innerHTML = '

Falha de conexão.

'; } }; }catch(e){ res.innerHTML = `

Falha de conexão.

`; } }; } PAGINAS["acessibilidade"] = { eyebrow:"Acessibilidade", titulo:"Acessibilidade", ref:false, intro:"A Prefeitura Municipal de Sabará trabalha para que este portal possa ser utilizado por todas as pessoas, independentemente de deficiência, tecnologia ou condição de acesso.", corpo: `

Nossas páginas seguem as diretrizes do e-MAG — Modelo de Acessibilidade em Governo Eletrônico, conforme o Decreto nº 5.296/2004. Acessibilidade significa garantir que pessoas com deficiência ou mobilidade reduzida possam participar de todas as atividades, produtos e serviços oferecidos — inclusive na internet.

Atalhos de navegação pelo teclado

O que é isto? São combinações de teclas que levam você direto a uma área do portal, sem precisar usar o mouse nem rolar a página. Serve para quem navega pelo teclado ou usa leitor de tela.

Como usar: segure a tecla Alt e, sem soltar, aperte o número. No Chrome e no Edge é Alt + número; em outros navegadores muda um pouco — a tabela abaixo mostra cada caso.

Pode clicar nos cartões acima para experimentar o atalho agora.

A combinação de teclas varia conforme o navegador utilizado:

NavegadorCombinação
Google Chrome e Microsoft Edge (Windows e Linux)Alt + número
Mozilla Firefox (Windows e Linux)Alt + Shift + número
macOS (Safari, Chrome e Firefox)Control + Option + número
OperaShift + Esc + número

Alto contraste

No topo de todas as páginas há o botão Alto contraste, que altera as cores do site para uma combinação de maior contraste — fundo preto, textos em branco e links em amarelo —, facilitando a leitura para pessoas com baixa visão. A opção permanece ativa enquanto você navega e pode ser desligada no mesmo botão.

Tamanho do texto

Também no topo das páginas estão os botões A+ e A−, que aumentam e diminuem o tamanho do conteúdo. O botão A retorna ao tamanho original. A preferência escolhida é mantida enquanto você navega pelo site.

Você também pode usar os recursos do próprio navegador:

  • Ctrl + + — aumentar o zoom
  • Ctrl + — diminuir o zoom
  • Ctrl + 0 — voltar ao tamanho padrão

Em computadores Mac, utilize a tecla Command (⌘) no lugar do Ctrl.

VLibras — conteúdo em Libras

Este portal disponibiliza o VLibras, conjunto de ferramentas do Governo Federal que traduz conteúdos digitais para a Língua Brasileira de Sinais (Libras). Para utilizá-lo, clique no ícone azul com o símbolo de Libras, no canto direito da tela, e selecione o texto que deseja traduzir.

O VLibras também está disponível para computadores, celulares e tablets.

Baixar o VLibras

Leitores de tela e tecnologias assistivas

Pessoas cegas ou com baixa visão podem navegar neste site com o auxílio de leitores de tela. Algumas opções gratuitas:

  • NVDA — leitor de tela gratuito para Windows
  • VoiceOver — já disponível no macOS, iPhone e iPad
  • TalkBack — já disponível em aparelhos Android
  • Orca — leitor de tela para Linux

Este portal também oferece a Leitura ao toque: ative no topo da página e aponte ou toque em um texto para ouvi-lo (atalho Alt + L).

Leis e decretos sobre acessibilidade

Decreto nº 5.296/2004Estabelece normas gerais e critérios básicos para a promoção da acessibilidade.
Lei nº 13.146/2015Lei Brasileira de Inclusão da Pessoa com Deficiência (Estatuto da Pessoa com Deficiência).
Decreto nº 6.949/2009Promulga a Convenção Internacional sobre os Direitos das Pessoas com Deficiência.
Decreto nº 7.724/2012Regulamenta a Lei de Acesso à Informação.
e-MAGModelo de Acessibilidade em Governo Eletrônico.

Dúvidas, sugestões e críticas

Se você encontrar alguma barreira de acessibilidade neste portal, ou tiver sugestões para melhorá-lo, entre em contato pela nossa Ouvidoria. Sua contribuição nos ajuda a tornar o site acessível a todas as pessoas.

Atendimento presencial

Rua Marquês de Sapucaí, 317 – Centro
Sabará – MG, 34505-600
Seg. a sex., 8h às 12h e 13h às 17h
Tel.: (31) 3672-7672

`, aoMontar: () => { const b = document.querySelector('[data-acs="contraste"]'); if(b) b.onclick = () => { const c = document.getElementById("btn-contraste"); if(c) c.click(); }; document.querySelectorAll("[data-atalho]").forEach(bt => bt.onclick = () => { const n = bt.dataset.atalho; if(n === "1"){ const c = document.getElementById("conteudo"); if(c){ c.setAttribute("tabindex","-1"); c.focus(); c.scrollIntoView({behavior:"smooth"}); } } if(n === "2"){ const m = document.getElementById("menu-toggle"); if(m) m.click(); } if(n === "3"){ const q = document.querySelector(".hero input, input[type=search]"); if(q){ q.focus(); q.scrollIntoView({block:"center", behavior:"smooth"}); } } if(n === "4"){ const r = document.getElementById("contato"); if(r){ r.setAttribute("tabindex","-1"); r.focus(); r.scrollIntoView({behavior:"smooth"}); } } if(n === "5"){ window.location.hash = "#/consultas"; } }); } }; /* ============ SERVIÇO DE INFORMAÇÃO AO CIDADÃO — SIC / e-SIC ============ */ /* ====== Ampliar foto (clique na foto do secretário) ====== */ function jiAmpliarFoto(src, legenda, cargo){ document.querySelectorAll(".amp-ov").forEach(m => m.remove()); const ov = document.createElement("div"); ov.className = "amp-ov"; ov.setAttribute("role","dialog"); ov.setAttribute("aria-modal","true"); ov.setAttribute("aria-label", "Foto de " + (legenda || "responsável")); ov.innerHTML = `
${esc(legenda|| ${legenda ? `
${esc(legenda)}${cargo?`${esc(cargo)}`:""}
` : ""}
`; const fechar = () => { ov.remove(); document.removeEventListener("keydown", tecla); }; const tecla = e => { if(e.key === "Escape") fechar(); }; ov.onclick = fechar; ov.querySelector(".amp-x").onclick = fechar; document.addEventListener("keydown", tecla); document.body.appendChild(ov); ov.querySelector(".amp-x").focus(); } /* ============== SECRETARIAS E ÓRGÃOS — lista e página própria ============= */ const SEC_GRUPOS = [["secretaria","Secretarias Municipais"],["orgao","Órgãos e Gerências"],["regional","Regionais"]]; async function jiSecretarias(host){ host.innerHTML = `

Carregando…

`; window.scrollTo(0,0); try{ const j = await (await fetch("/api/portal/secretarias")).json(); const porTipo = {}; (j.resultados||[]).forEach(s => (porTipo[s.tipo] = porTipo[s.tipo] || []).push(s)); let n = 0; const cartao = s => { const grad = s.cor ? `linear-gradient(150deg, ${s.cor}, ${s.cor}dd)` : _grad(n++); return `
${s.foto_url ? `` : ``}

${esc(s.nome)}

${s.responsavel ? `${esc(s.responsavel)}${s.cargo_responsavel?` · ${esc(s.cargo_responsavel)}`:""}` : ""}
${s.telefone ? ` ${esc(s.telefone)}` : ""} ${s.email ? ` ${esc(s.email)}` : ""}
Ver a secretaria
`; }; const secs = SEC_GRUPOS.filter(([k]) => (porTipo[k]||[]).length).map(([k,rot]) => `
Institucional

${esc(rot)}

${porTipo[k].map(cartao).join("")}
`).join(""); host.innerHTML = `
${jiMigalha("Secretarias e Regionais")} Institucional

Secretarias e Regionais

Estrutura administrativa da Prefeitura de Sabará: competências, responsáveis, endereços e formas de contato.

${secs}
`; }catch(e){ host.innerHTML = `

Não foi possível carregar as secretarias

`; } } /* Consultas de transparência que pertencem a cada secretaria. Os mesmos links do índice de consultas, mas exibidos DENTRO da página da secretaria — é o "filtrar pela secretaria" que faltava. A chave é o slug da secretaria; o valor é [Título da seção, [[rótulo, link], ...]]. */ const JI_CONSULTAS_SEC = { "educacao": ["Transparência da Educação", [ ["SIOPE — aplicação em educação", "#/t/siope"], ["Plano Municipal de Educação", "#/t/plano_educacao"], ["Conselhos (Fundeb e demais)", "#/t/conselhos_composicao"], ["Lista de espera em creches", "#/t/creches_espera"], ["Cadastro escolar", "#/cadastro-escolar"], ]], "saude": ["Transparência da Saúde", [ ["SIOPS — aplicação em saúde", "#/t/siops"], ["Planos e relatórios de saúde", "#/t/saude_planos"], ["Medicamentos do SUS (Remume)", "#/t/remume"], ["Estoque de medicamentos", "#/t/estoque_medicamentos"], ["Fila de regulação (consultas e exames)", "#/t/regulacao_fila"], ["Unidades e serviços de saúde", "#/t/unidades_saude"], ]], "assistencia-social": ["Transparência da Assistência Social", [ ["SIOPE — aplicação em educação", "#/t/siope"], ["Conselhos municipais — composição", "#/t/conselhos_composicao"], ["Cadastro habitacional", "#/habitacao"], ]], }; // aceita variações de slug ("secretaria-educacao", "educacao", "saude", …) function jiConsultasDaSecretaria(slug){ const chave = String(slug || "") .replace(/^secretaria-/, "") .replace(/^municipal-de-/, ""); let grupo = JI_CONSULTAS_SEC[chave]; if(!grupo){ // tenta casar por prefixo (ex.: "educacao-e-cultura" → "educacao") const k = Object.keys(JI_CONSULTAS_SEC).find(x => chave.startsWith(x)); grupo = k ? JI_CONSULTAS_SEC[k] : null; } if(!grupo) return ""; const [titulo, links] = grupo; const cartoes = links.map(([lb, u]) => ` ${esc(lb)} `).join(""); return `

${esc(titulo)}

Consultas de dados abertos desta secretaria. Consultas ainda sem registros mostram “nenhum registro” até a secretaria publicar.

${cartoes}
`; } async function jiSecretaria(host, slug){ host.innerHTML = `

Carregando…

`; window.scrollTo(0,0); try{ const r = await fetch("/api/portal/secretarias/" + encodeURIComponent(slug)); if(!r.ok) throw new Error("não encontrada"); const s = (await r.json()).secretaria; const paras = t => (t||"").split(/\n+/).filter(x=>x.trim()).map(p=>`

${esc(p)}

`).join(""); const kb = n => n > 1048576 ? (n/1048576).toFixed(1)+" MB" : Math.max(1,Math.round(n/1024))+" KB"; const grad = s.cor ? `linear-gradient(150deg, ${s.cor}, ${s.cor}dd)` : _grad(slug.length); const arqPorId = {}; (s.arquivos||[]).forEach(a => arqPorId[a.id] = a); const usados = new Set(); const listaArq = arr => arr.length ? `` : ""; const blocos = (s.blocos||[]).map(b => { const arr = (b.arquivos||[]).map(id => { usados.add(id); return arqPorId[id]; }).filter(Boolean); return `
${b.titulo ? `

${esc(b.titulo)}

` : ""}
${paras(b.texto)}
${listaArq(arr)}
`; }).join(""); const soltos = (s.arquivos||[]).filter(a => !usados.has(a.id)); const abas = [ s.competencias && ["comp","Competências","ti-list-check"], (s.sobre || s.curriculo) && ["sobre","Sobre","ti-user-star"], (s.blocos||[]).length && ["mais","Mais informações","ti-bookmark"], soltos.length && ["docs","Documentos","ti-files"], ].filter(Boolean); host.innerHTML = `
${jiMigalha(s.nome)}
${s.foto_url ? `${esc(s.responsavel||s.nome)} ` : ``}
Institucional

${esc(s.nome)}

${s.responsavel ? `

${esc(s.responsavel)}${esc(s.cargo_responsavel||"Responsável")}

` : ""}
${s.telefone ? `
Telefone${esc(s.telefone)}
` : ""} ${s.email ? `` : ""} ${s.endereco ? `
Endereço${esc(s.endereco)}
` : ""} ${s.funcionamento ? `
Funcionamento${esc(s.funcionamento)}
` : ""}
${abas.length > 1 ? `
${abas.map((a,i)=> ``).join("")}
` : ""} ${s.competencias ? `

Competências

${paras(s.competencias)}
` : ""} ${(s.sobre || s.curriculo) ? `
${s.sobre ? `

Sobre a secretaria

${paras(s.sobre)}
` : ""} ${s.curriculo ? `
${s.foto_url ? `` : ``}

${esc(s.responsavel||"Responsável")}

${esc(s.cargo_responsavel||"")}
${paras(s.curriculo)}
` : ""}
` : ""} ${(s.blocos||[]).length ? `
${blocos}
` : ""} ${soltos.length ? `

Documentos da secretaria

${listaArq(soltos)}
` : ""} ${jiConsultasDaSecretaria(slug)}
`; const abaBtns = host.querySelectorAll("#secp-abas .ouv-aba"); abaBtns.forEach(b => b.onclick = () => { abaBtns.forEach(x => x.classList.remove("ativa")); b.classList.add("ativa"); host.querySelectorAll(".secp-painel").forEach(p => p.hidden = p.dataset.secP !== b.dataset.sec); }); }catch(e){ host.innerHTML = `

Secretaria não encontrada

Ver todas as secretarias

`; } } PAGINAS["cronograma-cestas"] = { eyebrow:"Servidor", titulo:"Cronograma da Cesta de Alimentos", ref:false, intro:"Calendário de entrega da cesta de alimentos aos servidores municipais, orientações de retirada e o modelo de autorização para quem não puder comparecer.", aoMontar: () => { const hoje = new Date(), mesAtual = hoje.getMonth(); const linha = document.querySelector(`[data-mes="${mesAtual}"]`); if(linha){ linha.classList.add("cest-atual"); const t = linha.querySelector(".cest-tag"); if(t) t.textContent = "mês atual"; } }, corpo: () => { const MESES = [["Janeiro","17"],["Fevereiro","14"],["Março","14"],["Abril","11"], ["Maio","09"],["Junho","13"],["Julho","11"],["Agosto","08"],["Setembro","12"], ["Outubro","10"],["Novembro","14"],["Dezembro","EM ABERTO"]]; return `

Quem tem direito

Benefício concedido aos servidores que se enquadram até o nível P10 da tabela de cargos e salários da Prefeitura de Sabará.

Como funciona a entrega

A entrega é realizada exclusivamente no dia programado para cada mês, das 08h às 17h. Não há entrega em outra data, salvo nas situações previstas nos avisos abaixo.

Recursos Humanos

Rua Comendador Viana, 119 – Centro
Sabará – MG · CEP 34.505-340

Telefones

(31) 3672-7707
(31) 3672-7706

Horário de entrega

08h às 17h no dia programado

Cronograma de entrega · 2025

${MESES.map(([m,d],i) => `
${esc(m)} ${esc(d)} ${d==="EM ABERTO" ? "a definir" : "dia da entrega"}
`).join("")}

A data de dezembro será divulgada pela Secretaria Municipal de Recursos Humanos.

Não vai poder retirar?

O servidor impossibilitado de retirar a própria cesta pode autorizar outra pessoa. Para isso:

  1. Baixe a autorizaçãoUse o botão ao lado para baixar o modelo oficial.
  2. Preencha e assineComplete os dados do autorizado, inclusive o número do RG.
  3. Anexe um documento com fotoCópia legível de documento de identificação, para conferência da assinatura.
  4. Entregue no diaA pessoa autorizada apresenta os documentos no ato da retirada.

Persistindo a impossibilidade, a entrega será feita em data posterior definida pelo setor responsável, somente ao servidor que justificar a ausência por atestado médico ou documento equivalente.

Modelo oficial

Autorização para retirada da cesta de alimentos — Secretaria Municipal de Recursos Humanos.

Lembre-se de anexar cópia de documento com foto.

Avisos importantes

  • A entrega da cesta será realizada exclusivamente no dia programado para cada mês.
  • O horário de entrega é das 08h às 17h.
  • Quem não puder comparecer deve usar o modelo de autorização disponível nesta página.
  • A entrega em data posterior depende de justificativa por atestado médico ou documento equivalente.
`; } }; PAGINAS["concurso-publico"] = { eyebrow:"Servidores e Pessoal", titulo:"Concursos e Processos Seletivos", ref:false, intro:"Editais, inscrições, resultados, classificação e nomeações dos concursos públicos e processos seletivos da Prefeitura de Sabará.", corpo: () => `

Resultados

Gabaritos, classificação final, homologação e convocações.

Ver resultados →

Atos dos concursos e processos seletivos

Todas as etapas publicadas: edital, retificação, gabarito, classificação, homologação e nomeação. Use a busca por cargo, número do certame ou nome do candidato.

Dúvidas sobre um concurso

Questões sobre inscrição, prova, recurso ou convocação devem ser dirigidas à banca organizadora indicada no edital. Para dúvidas sobre a vida funcional após a nomeação, procure o Recursos Humanos.

Recursos Humanos

Rua Marquês de Sapucaí, 317 – Centro
Sabará – MG
(31) 3672-7707 / 3672-7706
recursoshumanos@sabara.mg.gov.br

Atendimento

Segunda a sexta · 08h às 12h e 13h às 17h

` }; PAGINAS["conselhos"] = { eyebrow:"Participação", titulo:"Conselhos e Fundos Municipais", ref:false, intro:"Os conselhos municipais são colegiados que acompanham, fiscalizam e deliberam sobre as políticas públicas. A composição é paritária entre poder público e sociedade civil.", corpo: () => `

Deliberação

Reúnem-se periodicamente para deliberar sobre a política do setor.

Fiscalização

Acompanham a execução e a aplicação dos recursos públicos.

Participação

Representantes da sociedade civil participam das decisões.

Transparência

Composição, atas e deliberações são publicadas no portal.

Composição e funcionamento

Conselheiros titulares e suplentes, segmento representado, mandato e ato de nomeação de cada conselho, inclusive o Conselho do FUNDEB.

Fundos municipais

Os fundos são vinculados a políticas específicas e têm a execução acompanhada pelo respectivo conselho.

Quer participar?

A composição dos conselhos é renovada periodicamente, por edital de chamamento público ou indicação das entidades representativas. Acompanhe as convocações nas notícias e na legislação municipal.

Informações

Cada conselho é vinculado a uma secretaria. Consulte a secretaria responsável na lista de Secretarias e Regionais.

Dúvidas

Use a Ouvidoria ou peça informações pelo e-SIC.

` }; PAGINAS["executivo-municipal"] = { eyebrow:"Institucional", titulo:"Executivo Municipal", ref:false, intro:"Responsáveis pela gestão do Poder Executivo Municipal de Sabará e a estrutura de governo.", aoMontar: async () => { const box = document.getElementById("exm-gestao"); if(!box) return; try{ const j = await (await fetch("/api/portal/secretarias")).json(); const ger = (j.resultados||[]).filter(x => x.tipo === "gestao"); if(!ger.length){ box.innerHTML = `

Informações da gestão em atualização.

`; return; } box.innerHTML = ger.map(g => `
${g.foto_url ? `${esc(g.responsavel||g.nome)}` : ``}
${esc(g.responsavel || g.nome)} ${esc(g.cargo_responsavel || g.nome)} ${g.email ? ` ${esc(g.email)}` : ""} Ver perfil
`).join(""); }catch(e){ box.innerHTML = `

Não foi possível carregar as informações da gestão.

`; } }, corpo: () => `

Chefia do Poder Executivo

O Prefeito é a autoridade máxima do Poder Executivo, auxiliado pelo Vice-Prefeito e pelos titulares das secretarias municipais.

Carregando…

Sede do Governo

Prefeitura Municipal de Sabará
Rua Marquês de Sapucaí, 317 – Centro
Sabará – MG · CEP 34505-600
(31) 3672-7672

Horário de atendimento

Segunda a sexta-feira, das 08h às 12h e das 13h às 17h.

Transparência da gestão

Remuneração dos agentes políticos, diárias e atos oficiais estão publicados nas consultas de transparência.

Estrutura do Poder Executivo

` }; /* ===== Sobre o portal — números que se atualizam sozinhos ===== */ PAGINAS["orcamento"] = { eyebrow:"Transparência", titulo:"Orçamento Municipal", ref:false, intro:"As três leis que definem para onde vai o dinheiro público do Município — PPA, LDO e LOA — e o acompanhamento da execução. É o ciclo orçamentário completo, do planejamento à prestação de contas.", corpo: () => `

As três leis do orçamento

Toda despesa pública nasce nessas três leis. Elas são aprovadas pela Câmara e definem o planejamento, as prioridades do ano e o orçamento propriamente dito.

Como o orçamento está sendo executado

Prestação de contas e relatórios fiscais

Entendendo o ciclo

O PPA vale por quatro anos e diz o que o governo pretende fazer. A LDO é anual e escolhe as prioridades do próximo ano dentro desse plano. A LOA transforma essas prioridades em números: quanto cada órgão recebe e para qual finalidade. Durante o ano, a execução é acompanhada pelos relatórios da Lei de Responsabilidade Fiscal e, ao final, pela prestação de contas julgada pelo Tribunal de Contas e pela Câmara.

Base legal

Art. 165 da Constituição Federal
Lei nº 4.320/1964
Lei Complementar nº 101/2000 (LRF)
Lei Complementar nº 131/2009

Dados abertos

Todas as consultas podem ser baixadas em CSV, PDF ou consumidas por sistemas.

` }; PAGINAS["sobre-portal"] = { eyebrow:"Portal do Cidadão", titulo:"Sobre o Portal e Atualização", ref:false, intro:"O que já está publicado, quando foi atualizado pela última vez e como o portal é mantido. Esta página é gerada automaticamente a partir do próprio conteúdo publicado.", aoMontar: async () => { const box = document.getElementById("sob-corpo"); const dt = s => s ? new Date(s).toLocaleDateString("pt-BR") : "—"; const dth = s => s ? new Date(s).toLocaleString("pt-BR",{dateStyle:"short",timeStyle:"short"}) : "—"; try{ const j = await (await fetch("/api/portal/sobre")).json(); const pct = j.consultas ? Math.round(j.consultas_com_dados / j.consultas * 100) : 0; const dims = Object.entries(j.por_dimensao).sort((a,b)=>b[1].registros-a[1].registros); box.innerHTML = `
${j.consultas}Consultas de transparência
${j.registros.toLocaleString("pt-BR")}Registros publicados
${j.documentos.toLocaleString("pt-BR")}Documentos no acervo
${j.secretarias}Secretarias e órgãos

Última atualização

Dados de transparência${dth(j.ultima_transparencia)} Acervo de documentos${dth(j.ultimo_documento)} Notícias${dth(j.ultima_noticia)}

Cobertura por área

${j.consultas_com_dados} de ${j.consultas} consultas já têm dados publicados (${pct}%). As demais estão preparadas e aguardam o envio da secretaria responsável.

${dims.map(([d,g]) => `
${esc(d)} ${g.com_dados}/${g.consultas}
`).join("")}
${(j.recentes||[]).length ? `

Publicações mais recentes

${j.recentes.map(r => ` ${esc(r.label)}${esc(r.dimensao)} ${dt(r.em)}`).join("")}
` : ""}

Página gerada em ${dth(j.atualizado_em)}. Os números vêm direto do banco de dados do portal — não há atualização manual.

`; }catch(e){ box.innerHTML = `
Não foi possível carregar os números do portal.
`; } }, corpo: () => `

O que é este portal

O Portal do Cidadão reúne, num só lugar, os serviços, as notícias e os dados públicos da Prefeitura Municipal de Sabará. Foi construído seguindo o Programa Nacional de Transparência Pública (PNTP/ATRICON), a Lei de Acesso à Informação (Lei nº 12.527/2011) e as diretrizes de acessibilidade do e-MAG.

Como o conteúdo é mantido

Cada secretaria publica os próprios dados pelo painel de gestão, com permissão restrita à sua área. Toda publicação registra data e responsável, e os dados ficam disponíveis em formato aberto (CSV, JSON e PDF).

Encontrou um erro?

Avise pela Ouvidoria ou peça a informação pelo e-SIC.

Dados abertos

Todo o conteúdo pode ser baixado e reutilizado.

Carregando os números do portal…

` }; PAGINAS["esic"] = { eyebrow:"Acesso à Informação", titulo:"e-SIC — Serviço de Informação ao Cidadão", ref:false, intro:"Canal oficial para pedidos de acesso à informação pública, previsto na Lei nº 12.527/2011 (LAI). Qualquer pessoa pode pedir informações ao Município, sem precisar justificar o motivo.", corpo: `

Como fazer um pedido de informação

O pedido pode ser feito pela internet, no sistema oficial Fala.BR, ou presencialmente no SIC. Basta informar nome, um meio de contato para a resposta e a descrição do que você quer saber.

Não é exigido envio de documentos, assinatura reconhecida, declaração de responsabilidade ou justificativa do pedido.

Prazo de resposta: até 20 dias, prorrogáveis por mais 10, mediante justificativa (art. 11 da Lei nº 12.527/2011). Havendo negativa, cabe recurso à autoridade superior.

Unidade responsável

Serviço de Informação ao Cidadão (SIC)
Controladoria-Geral do Município

Endereço

Rua Marquês de Sapucaí, 317 – Centro
Sabará – MG, CEP 34505-600

Horário de funcionamento

Segunda a sexta-feira
8h às 12h e 13h às 17h

Contato

Tel.: (31) 3672-7672
ouvidoria@sabara.mg.gov.br

Caminho do seu pedido

  1. RegistroVocê registra o pedido no Fala.BR ou presencialmente no SIC e recebe um número de protocolo.
  2. TriagemO SIC encaminha o pedido à secretaria que detém a informação e acompanha o prazo.
  3. RespostaA resposta chega pelo mesmo canal em até 20 dias, prorrogáveis por mais 10.
  4. RecursoSe a resposta for negada ou incompleta, você pode recorrer em até 10 dias à autoridade superior.

Transparência passiva — consultas

A Ouvidoria e o SIC funcionam de forma integrada: manifestações (denúncias, reclamações, sugestões e elogios) são tratadas pela Ouvidoria Municipal; pedidos de acesso a documentos e dados são tratados pelo SIC.

` }; PAGINAS["faq"] = { eyebrow:"Serviços ao cidadão", titulo:"Perguntas Frequentes", ref:false, intro:"Respostas rápidas para as dúvidas mais comuns sobre os serviços municipais.", corpo: `
Como emito a 2ª via do IPTU?

Acesse o Portal Tributário e escolha a opção de consulta/2ª via do IPTU. Você precisa do número de inscrição do imóvel (está no carnê).

Como solicito uma Certidão Negativa de Débitos?

A emissão é feita no Portal Tributário, na opção Certidões. A certidão sai na hora, em PDF, se não houver pendências.

Como faço um pedido de acesso à informação (e-SIC)?

Use o e-SIC pelo botão no topo do portal. O pedido é registrado na plataforma federal Fala.BR, com número de protocolo e prazo legal de resposta (Lei 12.527/2011).

Como abro um protocolo na Prefeitura?

Pelo Protocolo Digital, disponível na área do Cidadão. Você recebe um número e acompanha o andamento on-line.

Onde encontro os telefones das secretarias?

Na página Secretarias e contatos, com os contatos dos órgãos municipais.

Como acompanho licitações e editais?

Em Licitações você acessa o sistema oficial com os processos em andamento; os avisos também são publicados nas Notícias.

Como emitir Nota Fiscal de Serviços (NFS-e)?

Prestadores emitem pela página NFS-e, que abre o sistema oficial de emissão do Município.

Como me inscrevo em concursos e processos seletivos?

Os editais, inscrições e resultados ficam em Concurso Público.

` }; PAGINAS["privacidade"] = { eyebrow:"Acesso à Informação", titulo:"Política de Privacidade (LGPD)", ref:false, intro:"Como a Prefeitura de Sabará trata dados pessoais neste portal, conforme a Lei nº 13.709/2018 (LGPD).", corpo: `

1. Quem trata seus dados

O controlador dos dados pessoais tratados neste portal é o Município de Sabará/MG, com sede na Rua Marquês de Sapucaí, 317 – Centro, Sabará/MG. O tratamento observa a Lei nº 13.709/2018 (LGPD), a Lei nº 12.527/2011 (LAI) e a Lei Complementar nº 131/2009.

2. Quais dados tratamos

Este portal é majoritariamente informativo. Tratamos:

  • Dados de navegação (páginas acessadas e dados técnicos do dispositivo), usados apenas para funcionamento, segurança e estatística do site;
  • Dados de transparência ativa que o Município é obrigado a publicar (por exemplo, nome, cargo, lotação e remuneração de agentes públicos), tratados com base em obrigação legal;
  • Dados que você fornece voluntariamente ao usar os canais de atendimento (e-SIC e Ouvidoria). Esses pedidos são processados na plataforma federal Fala.BR, que possui tratamento e política próprios.

3. Base legal e finalidade

O tratamento se fundamenta principalmente no cumprimento de obrigação legal e regulatória e na execução de políticas públicas (art. 7º, II e art. 23 da LGPD). A publicação de informações de transparência ativa decorre da LAI e da LC 131/2009 — por isso a remuneração de servidores é informação pública, enquanto dados como o CPF completo permanecem protegidos.

4. Proteção do CPF

Nas consultas de remuneração, o CPF nunca é exibido por inteiro: mostramos apenas uma versão mascarada (ex.: ***.456.789-**). O número completo não é divulgado no portal.

5. Seus direitos (art. 18 da LGPD)

Você pode solicitar: confirmação da existência de tratamento; acesso aos dados; correção de dados incompletos ou desatualizados; anonimização, bloqueio ou eliminação de dados tratados em desconformidade com a lei; portabilidade; informação sobre compartilhamento; e, quando o tratamento se basear em consentimento, sua revogação. Esses direitos podem ser limitados quando os dados forem de divulgação obrigatória por lei.

6. Cookies

Utilizamos cookies essenciais para o funcionamento e a segurança do portal. Você pode bloqueá-los nas configurações do navegador, ciente de que isso pode afetar algumas funcionalidades.

7. Compartilhamento

Dados podem ser compartilhados com órgãos de controle e demais entes públicos quando exigido por lei ou para o cumprimento de competência legal.

8. Encarregado pelo Tratamento de Dados (DPO)

Em cumprimento ao art. 41 da Lei nº 13.709/2018 (LGPD), o Município designa o Encarregado pelo Tratamento de Dados Pessoais, responsável por atuar como canal de comunicação entre o titular dos dados, o Município e a Autoridade Nacional de Proteção de Dados (ANPD).

Encarregado(a): Controladoria-Geral do Município
Contato: dpo@sabara.mg.gov.br · (31) 3672-7672
Endereço: Rua Marquês de Sapucaí, 317 – Centro, Sabará – MG
Para exercer seus direitos (acesso, correção, exclusão e demais previstos no art. 18 da LGPD), utilize o contato acima ou os canais de e-SIC e Ouvidoria.

Última atualização: [data]. Esta política pode ser revisada a qualquer tempo; a versão vigente é sempre a publicada nesta página.

` }; /* --- Notícia individual (a partir de PUBLICACOES) --- */ function jiParags(txt){ txt = (txt||"").trim(); if(!txt) return ""; let blocos; if(/\n/.test(txt)) blocos = txt.split(/\n+/); else { const frases = txt.replace(/([.!?])\s+(?=[A-ZÀ-ÝÇ0-9"«])/g, "$1\u0001").split("\u0001"); blocos = []; for(let i=0;ib.trim()).filter(Boolean).map(b=>`

${esc(b)}

`).join(""); } function jiDefNoticia(n){ const rot = {noticia:"Notícia", edital:"Edital", aviso:"Aviso"}; const capa = n.imagem_url ? `${esc(n.titulo)}` : ""; const corpo = (n.corpo && n.corpo.trim()) ? jiParags(n.corpo) : `

${esc(n.resumo||"")}

O texto completo desta publicação está sendo migrado para o novo portal.

`; const volta = `

${svg(IC.doc,14)} Todas as notícias

`; return { eyebrow: rot[n.tag] || "Notícia", titulo: n.titulo, ref:false, corpo: `

${fmtData(n.data)}

${capa}${corpo}${volta}
` }; } function jiDefArtigo(rota){ const p = PUBLICACOES.find(x => x.url === ("#/" + rota)); if(!p) return null; return { eyebrow: p.tipo, titulo: p.titulo, corpo: `

${fmtData(p.data)}

${esc(p.resumo||"")}

O texto completo desta publicação está sendo migrado para o novo portal.

` }; } /* ================================ ROTEADOR ================================= */ /* Páginas dedicadas que espelham um tipo de transparência (podem receber link externo no painel) */ const CONSULTA_DEDICADA = { "divida-ativa":"divida_ativa", "contratos":"contratos", "licitacoes":"licitacoes", "servidores":"servidores" }; function jiRedirCard(host, titulo, eyebrow, link){ host.innerHTML = `
${jiMigalha(titulo||"Consulta")}${esc(eyebrow||"Transparência")}

${esc(titulo||"Consulta")}

${svg(IC.ext,30)}

Consulta no sistema oficial

A consulta de ${esc(titulo||"")} é feita em um sistema específico da Prefeitura. Clique abaixo para acessar os dados atualizados.

Acessar no sistema oficial ${svg(IC.ext,16)}
`; window.scrollTo(0,0); } function jiAbrir(rota){ const host = $("pagina-interna"); // rotas podem trazer parâmetros: #/t/despesas?q=termo · #/consultas?q=termo let jiParams = new URLSearchParams(""); const iInterr = rota.indexOf("?"); if(iInterr >= 0){ try{ jiParams = new URLSearchParams(rota.slice(iInterr + 1)); }catch(e){} rota = rota.slice(0, iInterr); } const jiQ = jiParams.get("q") || ""; if(typeof JI_ALIAS !== "undefined" && JI_ALIAS[rota]) rota = JI_ALIAS[rota]; let def = PAGINAS[rota]; const mNot = rota.match(/^noticia-(\d+)$/); if(!def && !mNot && rota.startsWith("noticia-")) def = jiDefArtigo(rota); // Páginas dedicadas que também têm consulta de transparência: se o admin // configurou um link externo para o tipo, redireciona (mesmo comportamento do #/t/). if(def && CONSULTA_DEDICADA[rota]){ host.innerHTML = `

Carregando…

`; window.scrollTo(0,0); apiPortal("/api/portal/transparencia/" + CONSULTA_DEDICADA[rota]) .then(cfg => { if(cfg && cfg.link_externo) jiRedirCard(host, def.titulo||"Consulta", def.eyebrow, cfg.link_externo); else jiRender(host, rota, def); }) .catch(() => jiRender(host, rota, def)); return; } if(def && !def.generica){ jiRender(host, rota, def); return; } const fallbackGenerica = def || null; const mTransp = rota.match(/^t\/([a-z0-9_-]+)$/); if(mTransp){ jiTabelaTransparencia(host, mTransp[1], jiQ); return; } if(rota === "consultas"){ jiIndiceTransparencia(host, jiQ); return; } if(rota === "secretarias" || rota === "competencias"){ jiSecretarias(host); return; } const mSec = rota.match(/^secretaria-([a-z0-9-]+)$/); if(mSec){ jiSecretaria(host, mSec[1]); return; } if(rota === "servicos"){ jiCatalogoServicos(host); return; } if(rota === "cartas-servicos"){ jiCartasHome(host); return; } const mCarta = rota.match(/^carta-([a-z0-9-]+)$/); if(mCarta){ jiCartaSecretaria(host, mCarta[1]); return; } host.innerHTML = `

Carregando…

`; window.scrollTo(0,0); if(mNot){ fetch("/api/portal/noticias/" + mNot[1]) .then(r => r.ok ? r.json() : null) .then(js => { if(js && js.noticia){ jiRender(host, rota, jiDefNoticia(js.noticia)); } else { jiRender(host, rota, { eyebrow:"Notícia", titulo:"Notícia não encontrada", intro:"Esta notícia não está mais disponível.", ref:false }); } }) .catch(() => jiRender(host, rota, { eyebrow:"Notícia", titulo:"Não foi possível carregar", intro:"Tente novamente em instantes.", ref:false })); return; } fetch("/api/paginas/" + encodeURIComponent(rota)) .then(r => r.ok ? r.json() : null) .then(js => { if(js && js.pagina){ const p = js.pagina; const def = { eyebrow:(p.eyebrow||p.categoria||"Portal do Cidadão"), titulo:p.titulo, intro:(p.intro||""), ref:false, corpo:(p.conteudo||""), cms:true }; const cru = (p.conteudo||"").trim(); if(cru.startsWith("@RICO@")){ try{ jiRenderRico(host, rota, def, JSON.parse(cru.slice(6))); return; } catch(e){ /* json inválido: cai no render normal */ } } jiRender(host, rota, def); } else if(fallbackGenerica){ jiRender(host, rota, fallbackGenerica); } else { /* Beco sem saída vira caminho: o serviço está no catálogo, mas o conteúdo ainda não foi publicado. Em vez de só informar, oferece o que fazer em seguida. */ jiRender(host, rota, { eyebrow:"Portal do Cidadão", titulo:"Conteúdo ainda não publicado", ref:false, intro:"Esta página faz parte do portal, mas o conteúdo ainda "+ "está sendo preparado pela Prefeitura.", corpo:`

Enquanto isso, você pode

` }); } }) .catch(() => { if(fallbackGenerica){ jiRender(host, rota, fallbackGenerica); return; } jiRender(host, rota, { eyebrow:"Portal do Cidadão", titulo:"Não foi possível carregar", intro:"Tente novamente em instantes.", ref:false }); }); } let JI_CAT = null; let JI_CAT_SEC = ""; function jiCatalogoServicos(host){ window.scrollTo(0,0); host.innerHTML = `
Servi\u00e7os ao cidad\u00e3o

Carta de Servi\u00e7os

Todos os servi\u00e7os da Prefeitura de Sabar\u00e1 num s\u00f3 lugar. Busque pelo nome ou filtre por secretaria.

Carregando servi\u00e7os\u2026

`; apiPortal("/api/portal/cartas").then(js => { JI_CAT = js; const wrap = host.querySelector(".cat-wrap"); const chips = [``] .concat(js.secretarias.map(x => ``)).join(""); wrap.innerHTML = `
${js.total}servi\u00e7os
${js.secretarias.length}secretarias
100%no portal
${chips}
`; wrap.querySelector("#cat-q").addEventListener("input", () => jiCatRender()); wrap.querySelector("#cat-chips").addEventListener("click", (e) => { const b = e.target.closest(".cat-chip"); if(!b) return; JI_CAT_SEC = b.dataset.sec || ""; wrap.querySelectorAll(".cat-chip").forEach(x => x.classList.toggle("ativo", x === b)); jiCatRender(); }); jiCatRender(); }).catch(() => { host.querySelector(".cat-wrap").innerHTML = `
${svg(IC.info,18)}
N\u00e3o foi poss\u00edvel carregar os servi\u00e7os.Tente de novo em instantes.
`; }); } function jiCatCampo(l,v){ return (v && v.trim()) ? `
${esc(l)}${esc(v)}
` : ""; } function jiCatRender(){ if(!JI_CAT) return; const q = (($("cat-q")||{}).value || "").trim().toLowerCase(); let lista = JI_CAT.servicos; if(JI_CAT_SEC) lista = lista.filter(s => s.slug === JI_CAT_SEC); if(q){ const termos = q.split(/\s+/); lista = lista.filter(s => { const alvo = (s.nome + " " + s.secretaria + " " + s.desc).toLowerCase(); return termos.every(t => alvo.indexOf(t) !== -1); }); } const info = $("cat-info"), res = $("cat-res"); if(info) info.textContent = `${lista.length} servi\u00e7o(s) encontrado(s)`; if(!lista.length){ res.innerHTML = `

Nenhum servi\u00e7o encontrado. Tente outra palavra.

`; return; } res.innerHTML = `
` + lista.map(s => { const grid = [jiCatCampo("Quem pode acessar",s.quem), jiCatCampo("Formas de acesso",s.formas), jiCatCampo("Prazo",s.prazo), jiCatCampo("Custo",s.custo), jiCatCampo("Telefone",s.tel), jiCatCampo("E-mail",s.email)].join(""); const desc = s.desc ? `

${esc(s.desc)}

` : ""; const docs = s.docs ? `
Documentos necess\u00e1rios

${esc(s.docs)}

` : ""; return `
${esc(s.nome)}`+ `${esc(s.secretaria)}\u25be`+ `
${desc}
${grid}
${docs}
`; }).join("") + `
`; } function jiFoto(url, iconeph, classe, tag, ampliar){ const ph = `
`; const retrato = url && url.indexOf("/static/img/") !== -1 ? " retrato" : ""; const img = url ? `` : ""; const et = tag ? `${esc(tag)}` : ""; return `
${ph}${img}${et}
`; } function jiMapaUrl(m){ // aceita string (endereço/nome) ou {q, lat, lng} if(typeof m === "string") return "https://www.google.com/maps/search/?api=1&query=" + encodeURIComponent(m); if(m && m.lat != null && m.lng != null) return "https://www.google.com/maps/search/?api=1&query=" + m.lat + "," + m.lng; if(m && m.q) return "https://www.google.com/maps/search/?api=1&query=" + encodeURIComponent(m.q); return ""; } function jiBlocoRico(b){ if(b.t === "destaques"){ const its = (b.itens||[]).map(i => `
${esc(i.n)}${(i.l||"").replace(/\n/g,"
")}
`).join(""); return `
${its}
`; } if(b.t === "cards"){ const cards = (b.itens||[]).map(c => { const meta = (c.meta||[]).map(m => ` ${esc(m.v)}`).join(""); const metaBox = meta ? `
${meta}
` : ""; const mapaUrl = c.mapa ? jiMapaUrl(c.mapa) : ""; const btnMapa = mapaUrl ? ` Como chegar` : ""; // card inteiro clicável quando tem UM destino (e não é o caso do "Como chegar") const clic = c.link && !c.mapa; const oT = clic ? "a" : "article"; const rota = clic ? ` href="${esc(c.link)}"${(c.link.startsWith('#')?'':' target="_blank" rel="noopener"')}` : ""; const cls = base => `class="${base}${clic?' rico-clic':''}"`; const link = (c.link && !clic) ? `${esc(c.linkTxt||"Saiba mais")} ` : ""; const pista = clic ? `
${esc(c.linkTxt||"Acessar")}
` : ""; const rodape = (btnMapa || link) ? `
${btnMapa}${link}
` : pista; if(c.img){ const foto = jiFoto(c.img, c.icone||"ti-photo", "rico-foto", c.tag, true); return `<${oT} ${cls("rico-card")}${rota}>${foto}

${esc(c.nome)}

${metaBox}

${esc(c.desc||"")}

${rodape}
`; } if(c.capa){ const tagCapa = c.tag ? `${esc(c.tag)}` : ""; const grad = `linear-gradient(150deg, ${c.capa} 0%, ${c.capa2||c.capa} 100%)`; const capa = `

${esc(c.nome)}

${tagCapa}
`; return `<${oT} ${cls("rico-card")}${rota}>${capa}
${metaBox}

${esc(c.desc||"")}

${rodape}
`; } const chip = c.tag ? `${esc(c.tag)}` : ""; return `<${oT} ${cls("rico-card rico-compact")}${rota}>

${esc(c.nome)}

${chip}
${metaBox}

${esc(c.desc||"")}

${rodape}
`; }).join(""); const cab = (b.titulo||b.sub||b.k) ? `
${b.k?`
${esc(b.k)}
`:""}${b.titulo?`

${esc(b.titulo)}

`:""}${b.sub?`

${esc(b.sub)}

`:""}
` : ""; return `
${cab}
${cards}
`; } if(b.t === "feature"){ const fimg = `
${b.img?``:""}
`; const itens = (b.itens||[]).map(i => `
  • ${esc(i.v||i)}
  • `).join(""); const listaBox = itens ? `
      ${itens}
    ` : ""; const txt = `
    ${b.k?`
    ${esc(b.k)}
    `:""}

    ${esc(b.titulo||"")}

    ${b.texto?`

    ${esc(b.texto)}

    `:""}${listaBox}
    `; return `
    ${fimg}${txt}
    `; } if(b.t === "cta"){ const btns = (b.acoes||[]).map(a => `${esc(a.txt)}`).join(""); return `

    ${esc(b.titulo||"")}

    ${b.texto?`

    ${esc(b.texto)}

    `:""}
    ${btns}
    `; } if(b.t === "texto"){ return `
    ${jiHtmlSeguro(b.html)}
    `; } return ""; } /* ====== Busca geral: destaca o termo dentro do texto já escapado ====== */ function _tgbMarcar(txt, termo){ const s = esc(String(txt == null ? "" : txt)); const t = String(termo || "").trim(); if(!t) return s; const alvo = esc(t).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); try { return s.replace(new RegExp("(" + alvo + ")", "gi"), "$1"); } catch(e){ return s; } } /* ====== Busca geral: monta o HTML dos resultados ====== */ function jiBuscaGeralHTML(js, termo){ const gs = js.grupos || [], docs = js.docs || []; const pgs = js.paginas || [], cons = js.consultas || []; const totalT = js.total || 0, totalD = js.docs_total || 0; if(!totalT && !totalD && !pgs.length && !cons.length){ return `

    Nenhum resultado para “${esc(termo)}”

    Tente outro termo: parte do nome da empresa, só os números do CNPJ, o número do contrato/empenho ou o objeto. A busca não diferencia maiúsculas de minúsculas nem acentos digitados a mais.

    `; } const blocoPag = pgs.length ? `` : ""; const blocoCons = cons.length ? `` : ""; const resumo = `
    ${totalT + totalD + pgs.length} resultado(s) para “${esc(termo)}”${pgs.length ? ` · ${pgs.length} página(s)` : ""}${gs.length ? ` · ${gs.length} consulta(s) com dados` : ""}${totalD ? ` · ${totalD} no acervo` : ""}
    `; const blocos = gs.map(g => { const itens = g.itens || []; const cols = (g.colunas || []).slice(0, 5); const temColArq = cols.some(c => c[0] === "arquivo"); const temAnexo = itens.some(r => r._arquivo_url); const th = cols.map(c => `${esc(c[1])}`).join("") + ((temAnexo && !temColArq) ? "Anexo" : ""); const linhas = itens.map(row => { const cels = cols.map(c => { if(c[0] === "arquivo" && row._arquivo_url) return `Ver documento`; const v = row[c[0]]; return `${(v === undefined || v === null || v === "") ? "—" : _tgbMarcar(v, termo)}`; }).join(""); const extra = (temAnexo && !temColArq) ? `${row._arquivo_url ? `PDF` : "—"}` : ""; return `${cels}${extra}`; }).join(""); const rota = `#/t/${encodeURIComponent(g.tipo)}?q=${encodeURIComponent(termo)}`; const rotulo = g.total > itens.length ? `Ver os ${g.total} resultados nesta consulta` : "Abrir a consulta completa"; return `
    ${esc(g.dimensao || "")}

    ${esc(g.label || g.tipo)}

    ${g.total} resultado(s)
    ${th}${linhas}
    `; }).join(""); const blocoDocs = docs.length ? `` : ""; return resumo + blocoPag + blocos + blocoDocs + blocoCons; } function jiIndiceTransparencia(host, qInicial){ host.innerHTML = `

    Carregando…

    `; window.scrollTo(0,0); fetch("/api/portal/transparencia/tipos").then(r => r.ok ? r.json() : Promise.reject()).then(js => { const tipos = js.tipos || {}; const grupos = {}; Object.keys(tipos).forEach(k => { const d = tipos[k].dimensao || "Outros"; (grupos[d] = grupos[d] || []).push([k, tipos[k]]); }); const ordem = ["Receita","Despesa","Convênios e Transferências","Recursos Humanos","Licitações","Contratos","Obras","Planejamento e Contas","Emendas Parlamentares","Renúncias de Receitas","Acesso à Informação (SIC)","Ouvidoria","Saúde","Educação e Assistência Social","LGPD e Governo Digital","Outros"]; const dims = Object.keys(grupos).sort((a,b)=>{ const ia=ordem.indexOf(a), ib=ordem.indexOf(b); return (ia<0?99:ia)-(ib<0?99:ib); }); const nTipos = Object.keys(tipos).length; // consultas que a auditoria classifica numa dimensão mas o cidadão procura em outra const ATALHOS = { "Licitações": [["processo_seletivo","Processos Seletivos e Concursos — Atos"], ["editais","Editais"]], "Recursos Humanos": [["editais","Editais de concursos e seleções"]], "Despesa": [["diarias","Diárias e Passagens"]], }; // Um icone por dimensao, em vez do mesmo ti-table repetido em tudo. // Icone so ajuda se distinguir; repetido, vira enfeite. const ICO_DIM = { "Informações Prioritárias":"ti-star", "Informações Institucionais":"ti-building-bank", "Receita":"ti-cash", "Despesa":"ti-receipt", "Convênios e Transferências":"ti-transfer", "Recursos Humanos":"ti-users", "Diárias":"ti-plane", "Licitações":"ti-gavel", "Contratos":"ti-file-description", "Obras":"ti-tools", "Planejamento e Contas":"ti-chart-line", "Acesso à Informação (SIC)":"ti-message-question", "Acessibilidade":"ti-accessible", "Ouvidoria":"ti-headset", "LGPD e Governo Digital":"ti-shield-lock", "Renúncias de Receitas":"ti-discount", "Emendas Parlamentares":"ti-writing", "Saúde":"ti-heartbeat", "Educação e Assistência Social":"ti-school", }; const secs = dims.map(d => { const ico = ICO_DIM[d] || "ti-table"; const jaTem = new Set(grupos[d].map(([k]) => k)); const itens = grupos[d].map(([k,v]) => `${esc(v.label)}`).join("") + (ATALHOS[d]||[]).filter(([k]) => tipos[k] && !jaTem.has(k)).map(([k,rot]) => `${esc(rot)}`).join(""); return `

    ${esc(d)}

    ${itens}
    `; }).join(""); host.innerHTML = `
    ${jiMigalha("Portal da Transparência")} Transparência

    Portal da Transparência

    ${nTipos} consultas de dados abertos do Município, organizadas por tema. Use a busca geral para procurar em todas de uma só vez.

    Busca geral

    Procure de uma vez nas ${nTipos} consultas e no acervo de atos: nome de empresa, CPF/CNPJ, número de contrato, empenho, servidor, objeto…

    A busca varre todos os campos de cada consulta — credor, objeto, CNPJ, número, histórico — e também leis, decretos, portarias e editais publicados.

    ${secs}

    As consultas exibem os dados publicados pela Prefeitura. Consultas ainda sem registros mostram “nenhum registro” até que os dados sejam enviados pela secretaria responsável.

    `; const inp = host.querySelector("#tgb-q"), btn = host.querySelector("#tgb-ir"), lim = host.querySelector("#tgb-limpar"), res = host.querySelector("#tgb-res"), idx = host.querySelector("#tgb-indice"); let deb, ultimo = "", seq = 0; function trocarHash(h){ try{ history.replaceState(null, "", h); }catch(e){} } function limpar(){ clearTimeout(deb); ultimo = ""; seq++; inp.value = ""; res.hidden = true; res.innerHTML = ""; idx.hidden = false; lim.hidden = true; trocarHash("#/consultas"); inp.focus(); } async function buscar(termo, forcar){ termo = (termo || "").trim(); if(!termo){ if(ultimo) limpar(); return; } if(termo.length < 2 || (termo === ultimo && !forcar)) return; ultimo = termo; const meu = ++seq; lim.hidden = false; idx.hidden = true; res.hidden = false; res.innerHTML = `

    Procurando “${esc(termo)}” em todas as consultas…

    `; trocarHash("#/consultas?q=" + encodeURIComponent(termo)); try{ const r = await fetch("/api/portal/transparencia/busca-geral?q=" + encodeURIComponent(termo) + "&por_grupo=5"); if(!r.ok) throw new Error("falha"); const dados = await r.json(); if(meu !== seq) return; res.innerHTML = jiBuscaGeralHTML(dados, termo); }catch(e){ if(meu !== seq) return; res.innerHTML = `

    Não foi possível concluir a busca

    Tente novamente em instantes.

    `; } } btn.addEventListener("click", () => buscar(inp.value, true)); lim.addEventListener("click", limpar); inp.addEventListener("keydown", e => { if(e.key === "Enter"){ e.preventDefault(); clearTimeout(deb); buscar(inp.value, true); } }); inp.addEventListener("input", () => { clearTimeout(deb); deb = setTimeout(() => buscar(inp.value), 450); }); if(qInicial && qInicial.trim().length >= 2) buscar(qInicial, true); }).catch(() => { host.innerHTML = `

    Não foi possível carregar as consultas

    `; }); } function jiTabelaTransparencia(host, tipo, qInicial){ const estado = { tipo, ano:"", q:(qInicial || ""), pagina:1, tam:20, dados:null, ocultas:new Set(), cheia:false }; try{ (JSON.parse(localStorage.getItem("tp_ocultas_"+tipo)||"[]")).forEach(k=>estado.ocultas.add(k)); }catch(e){} const fmtData = (iso) => { if(!iso) return "—"; const d=new Date(iso); return d.toLocaleDateString("pt-BR")+" "+d.toLocaleTimeString("pt-BR",{hour:"2-digit",minute:"2-digit"}); }; function carregar(){ const u = `/api/portal/transparencia/${encodeURIComponent(tipo)}?ano=${encodeURIComponent(estado.ano)}&q=${encodeURIComponent(estado.q)}&pagina=${estado.pagina}&tam=${estado.tam}`; const alvo = host.querySelector("#tp-corpo"); if(alvo) alvo.innerHTML = `Carregando…`; fetch(u).then(r => r.ok ? r.json() : Promise.reject()).then(js => { estado.dados = js; pintar(js); }) .catch(() => { host.innerHTML = `

    Não foi possível carregar

    Tente novamente em instantes.

    `; }); } function pintar(js){ if(js.link_externo){ host.innerHTML = `
    ${jiMigalha(js.titulo || "Transparência")} Transparência · ${esc(js.dimensao||"")}

    ${esc(js.titulo||"")}

    ${js.intro?`

    ${esc(js.intro)}

    `:""}
    ${svg(IC.ext,30)}

    Consulta no sistema oficial

    Esta consulta de ${esc(js.label||js.titulo||"")} é disponibilizada em um sistema específico da Prefeitura. Clique abaixo para acessar os dados atualizados.

    Acessar no sistema oficial ${svg(IC.ext,16)}
    `; return; } const todasCols = js.colunas || []; const cols = todasCols.filter(c => !estado.ocultas.has(c[0])); const densa = cols.length > 8 ? " tp-densa" : ""; const filtroUrl = `ano=${encodeURIComponent(estado.ano)}&q=${encodeURIComponent(estado.q)}`; const csvUrl = `/api/portal/transparencia/${encodeURIComponent(tipo)}.csv?${filtroUrl}`; const pdfUrl = `/api/portal/transparencia/${encodeURIComponent(tipo)}.pdf?${filtroUrl}`; const optAnos = [''].concat((js.anos||[]).map(a=>``)).join(""); const totalPag = Math.max(1, Math.ceil((js.total||0)/estado.tam)); const linhas = (js.resultados||[]).map(row => { const cels = cols.map(c=>{ const v = row[c[0]]||""; // se a coluna é "arquivo" e há PDF anexado, vira botão if(c[0]==="arquivo" && row._arquivo_url){ return `${svg(IC.ext,14)} Ver documento`; } return `${esc(v||"—")}`; }).join(""); // se tem PDF mas não há coluna "arquivo", acrescenta uma célula de ação no fim const temColArq = cols.some(c=>c[0]==="arquivo"); const extra = (!temColArq && row._arquivo_url) ? `${svg(IC.ext,14)} Ver documento` : ""; return `${cels}${extra}`; }).join("") || `Nenhum registro encontrado para este filtro.`; host.innerHTML = `
    ${jiMigalha(js.titulo || "Transparência")} Transparência · ${esc(js.dimensao||"")}

    ${esc(js.titulo||"")}

    ${js.intro?`

    ${esc(js.intro)}

    `:""}

    Atualizado em ${fmtData(js.atualizado_em)}

    Baixar CSV/Excel Baixar PDF
    ${cols.map(c=>``).join("")}${linhas}
    ${esc(c[1])}
    ${js.total||0} registro(s)
    Página ${estado.pagina} de ${totalPag}

    Dados publicados pela Prefeitura Municipal de Sabará. Formato aberto (CSV) disponível para download. Fonte: sistema de contas públicas do Município.

    `; const sec = host.querySelector(".rico-sec"); if(sec && densa) sec.classList.add("tp-secao-larga"); if(estado.cheia && sec) sec.classList.add("tp-larga"); const btnCheia = host.querySelector("#tp-cheia"); if(btnCheia){ if(estado.cheia) btnCheia.classList.add("on"); btnCheia.onclick = () => { estado.cheia = !estado.cheia; sec.classList.toggle("tp-larga", estado.cheia); btnCheia.classList.toggle("on", estado.cheia); btnCheia.innerHTML = estado.cheia ? ` Largura normal` : ` Tela cheia`; }; } const colBtn = host.querySelector("#tp-colbtn"), colMenu = host.querySelector("#tp-colmenu"); if(colBtn){ colBtn.onclick = e => { e.stopPropagation(); const ab = colMenu.hasAttribute("hidden"); if(ab) colMenu.removeAttribute("hidden"); else colMenu.setAttribute("hidden",""); colBtn.setAttribute("aria-expanded", String(ab)); }; document.addEventListener("click", ev => { if(colMenu && !colMenu.hidden && !colMenu.contains(ev.target) && ev.target !== colBtn) colMenu.setAttribute("hidden",""); }); const salvar = () => { try{ localStorage.setItem("tp_ocultas_"+tipo, JSON.stringify([...estado.ocultas])); }catch(e){} }; colMenu.querySelectorAll("input[data-col]").forEach(inp => inp.onchange = () => { const k = inp.dataset.col; if(inp.checked) estado.ocultas.delete(k); else estado.ocultas.add(k); if(todasCols.length - estado.ocultas.size < 1){ estado.ocultas.delete(k); inp.checked = true; return; } salvar(); pintar(estado.dados); }); const todas = host.querySelector("#tp-coltodas"); if(todas) todas.onclick = () => { estado.ocultas.clear(); salvar(); pintar(estado.dados); }; } const ano = host.querySelector("#tp-ano"); const q = host.querySelector("#tp-q"); let deb; ano.addEventListener("change", () => { estado.ano = ano.value; estado.pagina = 1; carregar(); }); q.addEventListener("input", () => { clearTimeout(deb); deb = setTimeout(() => { estado.q = q.value; estado.pagina = 1; carregar(); }, 350); }); const ant = host.querySelector("#tp-ant"), prox = host.querySelector("#tp-prox"); if(ant) ant.addEventListener("click", () => { if(estado.pagina>1){ estado.pagina--; carregar(); } }); if(prox) prox.addEventListener("click", () => { estado.pagina++; carregar(); }); // mantém foco no campo de busca ao repintar if(document.activeElement && document.activeElement.id === "tp-q"){} } carregar(); window.scrollTo(0,0); } /* ==== Carta de Serviços — telas interativas (busca geral, por secretaria, detalhe) ==== */ let CARTAS_CACHE=null, _SVC_ATUAL=[], _SVC_TODOS=[]; async function _cartasData(){ if(CARTAS_CACHE) return CARTAS_CACHE; const r=await fetch("/api/portal/cartas"); if(!r.ok) throw new Error("falha"); CARTAS_CACHE=await r.json(); return CARTAS_CACHE; } const _GRADS=["#163F6C,#1B4A7E","#0F2E50,#215732","#7A3F6B,#9c5588","#856820,#b8893a","#1c5a8a,#2b7db8","#215732,#2e8b57","#4a3f7a,#6a5fa0","#8a3f3f,#b85c5c"]; function _grad(i){ const p=_GRADS[i%_GRADS.length].split(","); return `linear-gradient(150deg,${p[0]},${p[1]})`; } function _cabecaCarta(kicker,titulo,intro){ return `
    ${esc(kicker)}

    ${esc(titulo)}

    ${intro?`

    ${esc(intro)}

    `:""}
    `; } function _svcCard(s,i){ return ``; } function jiSvcDetalhe(i){ const s=_SVC_ATUAL[i]; if(!s) return; const campo=(l,v)=> (v&&String(v).trim())?`
    ${l}${esc(v)}
    `:""; const grid=[campo("Quem pode acessar",s.quem),campo("Formas de acesso",s.formas),campo("Prazo",s.prazo),campo("Custo",s.custo),campo("Telefone",s.tel),campo("E-mail",s.email)].join(""); const desc=(s.desc&&s.desc.trim())?`

    ${esc(s.desc)}

    `:""; const docs=(s.docs&&s.docs.trim())?`
    Documentos necessários

    ${esc(s.docs)}

    `:""; const contato=[]; if(s.tel&&s.tel.trim()) contato.push(` Ligar`); if(s.email&&s.email.trim()) contato.push(` Enviar e-mail`); const host=document.createElement("div"); host.id="svc-modal-host"; host.innerHTML=`
    `; document.body.appendChild(host); document.body.style.overflow="hidden"; document.addEventListener("keydown", function esc(ev){ if(ev.key==="Escape"){ jiSvcFechar(); document.removeEventListener("keydown", esc); } }); } function jiSvcFechar(){ const h=$("svc-modal-host"); if(h) h.remove(); document.body.style.overflow=""; } async function jiCartasHome(host){ host.innerHTML=`

    Carregando serviços…

    `; window.scrollTo(0,0); let data; try{ data=await _cartasData(); }catch(e){ host.innerHTML=`

    Não foi possível carregar os serviços. Tente novamente.

    `; return; } const secs=data.secretarias||[]; _SVC_TODOS=data.servicos||[]; const cards=secs.map((sc,i)=>` ${esc(sc.nome)} ${sc.n} serviço${sc.n==1?'':'s'}`).join(""); host.innerHTML=_cabecaCarta("Serviços ao cidadão","Carta de Serviços", `Todos os serviços da Prefeitura de Sabará (${data.total}) num só lugar. Busque por um serviço ou escolha a secretaria.`)+ `

    Secretarias e órgãos

    ${cards}
    `; const inp=$("svc-q"), res=$("svc-res"); const run=()=>{ const q=inp.value.trim().toLowerCase(); if(!q){ res.innerHTML=""; return; } const hits=_SVC_TODOS.filter(s=>(s.nome+" "+s.secretaria+" "+(s.desc||"")).toLowerCase().includes(q)).slice(0,50); _SVC_ATUAL=hits; res.innerHTML=hits.length ? `

    ${hits.length} serviço${hits.length==1?'':'s'} encontrado${hits.length==1?'':'s'}

    ${hits.map((s,i)=>_svcCard(s,i)).join("")}
    ` : `

    Nenhum serviço encontrado para “${esc(q)}”. Tente outra palavra.

    `; }; inp.addEventListener("input", run); inp.focus(); } async function jiCartaSecretaria(host, slug){ host.innerHTML=`

    Carregando…

    `; window.scrollTo(0,0); let data; try{ data=await _cartasData(); }catch(e){ host.innerHTML=`

    Não foi possível carregar.

    `; return; } const sec=(data.secretarias||[]).find(x=>x.slug===slug); const servs=(data.servicos||[]).filter(s=>s.slug===slug); if(!sec){ host.innerHTML=_cabecaCarta("Carta de Serviços","Secretaria não encontrada","")+`
    `; return; } host.innerHTML=_cabecaCarta("Carta de Serviços — "+sec.nome, sec.nome, `${sec.n} serviço${sec.n==1?'':'s'} desta secretaria. Toque em um serviço para ver quem pode acessar, documentos, prazo, custo e contato.`)+ `
    `; const inp=$("svc-q"), res=$("svc-res"); const render=(list)=>{ _SVC_ATUAL=list; res.innerHTML=list.length?`
    ${list.map((s,i)=>_svcCard(s,i)).join("")}
    ` :`

    Nenhum serviço encontrado.

    `; }; render(servs); inp.addEventListener("input", ()=>{ const q=inp.value.trim().toLowerCase(); render(q?servs.filter(s=>(s.nome+" "+(s.desc||"")+" "+(s.docs||"")).toLowerCase().includes(q)):servs); }); } function jiRenderRico(host, rota, def, R){ const heroImg = (R.hero && R.hero.img) ? `
    ` : `
    `; const blocos = (R.blocos||[]).map(jiBlocoRico).join(""); host.innerHTML = `
    ${heroImg}
    ${jiMigalha(def.titulo)} ${esc(def.eyebrow || (R.hero&&R.hero.kicker) || "Portal do Cidadão")}

    ${esc(def.titulo)}

    ${def.intro ? `

    ${esc(def.intro)}

    ` : ""}
    ${blocos}
    `; const texto = host.querySelector(".ji-texto"); if(texto) jiLinkify(texto); jiLigarLightbox(host); window.scrollTo(0,0); } function jiLigarLightbox(host){ host.querySelectorAll("img.ampliavel").forEach(im => { im.addEventListener("click", () => { const lb = document.createElement("div"); lb.className = "rico-lightbox"; lb.innerHTML = ``; document.body.appendChild(lb); requestAnimationFrame(() => lb.classList.add("on")); const fecha = () => { lb.classList.remove("on"); setTimeout(() => lb.remove(), 200); }; lb.addEventListener("click", e => { if(e.target === lb || e.target.classList.contains("fechar")) fecha(); }); document.addEventListener("keydown", function esc(ev){ if(ev.key === "Escape"){ fecha(); document.removeEventListener("keydown", esc); } }); }); }); } function jiHtmlSeguro(bruto){ //